聊聊 JavaScript 的原型

JavaScript 中的原型也是一个非常让人头疼的东西,很多前端同学对此也是一知半解,比如我。今天我们就好好捋一捋这个原型。

创建对象的方式

下面就是创建对象的几种方式:

var o1 = {
    a: 123,
    b: 'hello world'
}
console.log(o1.b)


function fun2() {
    this.a = 33
    this.b = 'hello o2'
}

var o2 = new fun2()
console.log(o2.b)

class Fun3 {
    constructor() {
        this.a = 365
        this.b = 'hello class'
    }
}
var o3 = new Fun3()
console.log(o3.b)

有人说这是三种创建方式,但是我认为其实是两种创建方式(因为 class 语法糖的本质还是 function):直接定义对象使用 new 关键词构造对象

原型和原型链

当我们创建了一个对象之后,就产生了原型(Object.create(null) 是特例)。

prototype 和 __proto__ 的区别

__proto__ 是一个非正式的属性,很多环境中不支持该属性。它指向当前对象的原型。如下图:

__proto__

上面的代码是一段原型继承,可以看到对象 obj1 继承了对象 obj,所以 obj1 的 __proto__ 就指向了 obj,而 obj 的 __proto__ 则指向了 Object。所有对象的原型链最终都将指向 Object。

而关于 prototype 我摘录了一段话:

当你创建函数时,JS 会为这个函数自动添加 prototype 属性,值是一个有 constructor 属性的对象。而一旦你把这个函数当作构造函数(constructor)调用(即通过new关键字调用),那么 JS 就会帮你创建该构造函数的实例,实例继承构造函数 prototype 的所有属性和方法。

prototype

可以看到,对象 bar 的 __proto__ 属性指向了函数 func 的 prototype

总结下,__proto__ 指向原型,而 prototype 是函数独有且构造的对象原型指向 prototype

理解原型链

每个对象都是原型,而对象之间是可以继承的。所以就产生了原型链。看图说话:

原型链

很好理解了,我们创建了四个对象逐层进行原型继承。最后打印 obj3 对象可以看到 obj3 -> obj2 -> obj1 -> obj -> Object 这就是原型链。

如果我要在 obj3 对象上访问 a 属性,那么 JavaScript 就会顺着原型链逐层往下找,最终在 obj 对象上找到了a 属性,这就是原型链查找数据的方式。如果找到 Object 也没有找到属性就返回 undefined

原型链查找

为对象指定原型的两种方式

那么如何为对象添加原型呢?

1. new 关键字

第一种就是通过构造器的方式来创建。

function Foo () {
    this.a = 11
    this.b = 22
}
Foo.prototype.c = 33
Foo.prototype.func = () => {
    console.log('hello')
}

var f = new Foo()

console.log(f)
console.log(Object.getPrototypeOf(f))

当然,不得不说的是 ES6 的 class 语法糖写法:

class Foo {
    constructor() {
        this.a = 11
        this.b = 22
    }

    func() {
        console.log('hello')
    }
}

var f = new Foo()

两者其实是一样的效果,但是 class 写法更接近常规的类写法。(终于可以让 function 回归它原本的作用上了。)

2. Object.create(obj) 面向对象

Object.create() 可以很好的实现原型继承行为,也能通过 Object API 来修改原型:

var obj = { a: 123, b: 456 }
Object.setPrototypeOf(obj, { c: 789 })
var obj2 = Object.create(obj)
obj2.e = 555

代码输出结果如下图,的确实现了为对象指定原型的行为。

原型继承和修改

引用流还是复制流?

使用 JavaScript 原型是特别要主义的一个点是:JavaScript 对于原型的继承是一种引用行为,即所引用的对象改变,继承对象的原型也会改变。

与之相反的,有些语言会使用复制的方式。即在原型继承时复制一份原型到当前对象,从此被复制的对象和复制对象再无瓜葛。

总结

随着 Object.create() 等一系列新 API 和 ES6 的 class 写法的出现,使用 function 作为构造器并使用 prototype 来修改原型的方式将逐渐被抛弃。但是由于历史原因这部分知识还是要理解其中原理的。

__proto__ 属性是非正式属性,不适合在通用场景下使用。

而对于原型的写法,我认为有两种不错的处理方式:

  1. 完全使用 class 构造器写法来替代使用 function 构造器的写法来进行面向类的开发方式。
  2. 放弃原型写法,使用 Object 系列 API 进行面向对象的开发(行为委托就是这样的方式)。

最后

关于原型,先聊这么多。明天我们聊聊基于 Object API 来实现的面向对象模式 —— 行为委托,敬请期待。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容