话不多说,直接上图!
请记住以下几个原则:
- 1、对象内部具有
[[Prototype]]
属性,该属性不可直接访问,浏览器通过__proto__
(两条‘_’)可以让用户读写该内部属性,最重要的是,该属性指向创建本对象的原型对象。 - 2、每个原型对象内部都有一个独有属性
constructor
,指向该原型对象的构造函数。 - 3、原型对象也是对象,因此它也有自己的
__proto__
属性,最终会指向Object.prototype
记住了?很好,现在开始根据这三个原则去理解原型链图。
- 线(1):person1是Person的实例对象,根据原则1,person1的
__proto__
属性指向person1的原型对象,所以person1.__proto__ = Person.prototype
- 线(2):根据原则2,原型对象
Person.prototype
的constructor
属性指向它的构造函数,也就是Person
- 线(3):原型对象也是对象,它也有自己的原型链,因此它的
__proto__
属性指向创建它的原型对象,也就是Object.prototype
- 线(4)不用解释了吧
- 线(5)同线(2)
- 线(6)同线(4)
- 线(7)本质上,
Object
也是由Function
创建的,因此Object.prototype
指向Fucntion.prototype
- 线(8)同线(4)
- 线(9)
Obect.prototype
对象和Function.prototype
对象都是浏览器创建的,它们并非谁的实例。通过__proto__
属性将二者联系起来,从而使得函数也是对象。
- 线(10)既然函数也是对象,那么构造函数
Person
也有自己的__proto__
属性,而所有的函数本质上都可以写成new Function('...')
的形式,因此构造函数Person
是Function
的实例,所以Person.__proto__
指向Function.prototype
- 线(11)同线(4)
- 线(12),有了
Function.prototype
后,才有了Function
。而为了不产生混淆,就将Function.proto
指向Function.prototype
。
以上重点留意的就是线(7)、(9)以及(12),其他的理解了三条原则就能自己推理出来。
综上,我们可以有以下结论:
- 并非所有的对象都是实例,但是实例却都是对象。如
Function.prototype
是对象,但却并非谁的实例。 - 实例对象和原型对象之间、原型对象和构造函数之间都有直接联系,而实例对象和构造函数没有直接联系。如
person1
和Person.prototype
有直接联系,Person.prototype
和Person
有直接联系,但person1
和Person
没有直接联系。 - 实例对象内部的
__proto__
属性指向创建该对象的原型对象,而原型对象也是对象,它也有自己的原型对象并继承其属性,这就构成了原型对象链。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。