首先我们先知道以下几点:
- 在对象中含有一个
__proto__
的属性。 - 在函数(也属于对象)中含有
__proto__
和prototype
两个属性。 __proto__
会指向构造函数的prototype
属性,而继承的方法也是存在构造函数的此属性中。
然后我们以const arr = []
为例进行梳理:
arr
是一个通过new Array()
实例化的对象,所以他有一个__proto__
属性,指向Array
(构造函数)的prototype
属性,Array
函数的一些原生方法(push,pop,shift...
)在prototype
属性中,arr
从这里继承了这些方法,所以我们可以调用arr.push()
, 另外,Array.prototype
中有一个constructor
指向Array
函数本身,这样我们可以得到:Array === Array.prototype.constructor
。- 此时我们到了
Array.prototype
中,Array.prototype
也是一个对象,他也有一个__proto__
的属性,他的__proto__
指向了Object.prototype
,所以arr对象中也有了Object
的方法,比如arr.hasOwnProperty
。 - 我们来到了
Object.prototype
这里,同样他也是一个对象,但是他就比较特殊了,他的__proto__
指向的是NULL
,也就是原型链的顶端。 - 对于
Object
和Array
这两个构造函数(同样也是函数),他们的__proto__
则指向了Function.prototype
(注意的是所有的函数__proto__
亦如此),函数都继承了Function
中call
,bind
,toString
之类的方法:
Function.__proto__
也指向了Function.prototype
,所以有了Function.__proto__ === Function.prototype // true
,同时Function的prototype也是一个对象,他跟其他的一样,Function.prototype.__proto
指向了Object.prototype
,最终Object.prototype.__proto__ === Null
,此时这些都通了,源头就是一个NULL
- 最终附上一副图吧: