前端必知必会,你不知道的前端

从头到尾通俗理解原型链

2019-04-28  本文已影响17人  赵永盛

prototype 和 [[proto]] 什么关系?

prototype:显式原型
[[proto]]: 隐式原型
注意:简书不识别 “__ proto __”, 本文用 [[proto]] 替代

构造函数(就是普通的函数啦)都有 prototype 属性
对象都有 [[proto]] 属性,指向创建该对象的构造函数的 prototype.

clipboard.png

所以,关系理解清楚了。就是这么个关系。

用途:prototype 这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法

js 一切都可以看作是对象,方法也是对象, prototype 也是对象,既然是对象,那么就也有 [[proto]]

clipboard.png

可以看出来了,原型链 指的是:[[proto]] 构建的链条,而不是 prototype

再来看看 prototype 对象有什么属性:


clipboard.png

只有两个属性:
constructor
[[proto]]

其中 constructor 方法 指向构造函数自身,所以:


clipboard.png

所以,下面的式子也是成立的:


clipboard.png

既然, prototype 是一个对象,那么创建该对象的构造函数就是 Object 了,所以:


clipboard.png

继续, 那么 Object.prototype 又包含什么属性呢?


clipboard.png

可以看到继续往下走,就没有 [[proto]] 属性了。
所以: Object.prototype.[[proto]] === null
原型链的尽头 是 null:


clipboard.png

前面说了,一切皆对象,函数也不例外,我们这里叫它 函数对象。既然是对象,那么就有
[[proto]] 属性,前面只讨论了函数的 prototype 属性,现在我们讨论 函数的 [[proto]] 属性:

  1. 所有函数的 [[proto]] 都指向 Function.prototype
    是一个空函数

根据前面的 prototype 和 [[proto]] 对应关系,得出 其它函数都是由 Function 构造的:


clipboard.png

可以看到 new Function() 之后,结果还是一个函数。
所有函数对象都是 Function 的实例:


clipboard.png
clipboard.png

包括 Function 函数自身:


clipboard.png
clipboard.png
clipboard.png
包括一些包装类:
clipboard.png

注意 Object 也是一个函数,那么 Object 函数也是 由 Function 创建的:


clipboard.png

同理, Function 也是函数对象,那么它的 [[proto]] 是什么呢?


clipboard.png

这就不难理解为什么 Function instanceof Function === true 了

前面说的函数对象的 prototype 是一个对象,那么我们看看 Function 的 prototype:


clipboard.png

这里就不是单纯的一个对象了,而是一个函数。这也是 js 中唯一一个:
typeof XXX.prototype === 'function' 的 prototype

Function.prototype 虽然是函数,也是一个函数对象, 那么 它的 [[proto]] 指向 Object.prototype:


clipboard.png

好了,总体就是这么个关系,用图来总结一下:


clipboard.png

如何看这个图?
首先纵向 3 列:
第一列:创建的对象实例。包括 Foo, Object 创建的
第二列:提到三个函数,Foo, Object, Function
第三列:函数的 prototypes

第二列,第三列之间的关系一目了然:
Foo.prototype === Foo.prototype
Foo.prototype.constructor === Foo
Object, Function 同理

第一列,第二列之间的关系,就是实例是由构造函数 new 出来的,其它函数是由 Function 构造出来的,包括 Foo,Object.

第一列,第三列关系, 上面都有讲到:
实例作为对象:
f1.[[proto]] === Foo.prototype
o1.[[proto]] === Object.prototype

上面讲到:
构造函数的 [[proto]] === Function.prototype, 包括 Function 自身
所以:
Foo.[[proto]] === Function.prototype
Object.[[proto]] === Function.prototype
Function.[[proto]] === Function.prototype

prototype 作为一个对象,那么它的构造函数就是 Object. 所以:
Foo.prototype.[[proto]] === Object.prototype
Function.prototype.[[proto]] === Object.prototype
最后,到顶了:
Object.prototype.[[proto]] === null
(有人较真了,给你提醒: Object.[[proto]] === Function.prototype)

上一篇 下一篇

猜你喜欢

热点阅读