所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
所有函数除了有_proto_属性之外还拥有prototype属性(显式原型)
原型对象:每创建一个函数,该函数会自动带有一个prototype属性,该属性是一个指针,指向了一个对象,我们称之为原型对象。
函数除了有_proto_属性之外还拥有prototype属性,我们可以借助构造函数来寻找二者之间的关系
下图是关于原型链关系的关系图
通过图可以简单总结出:
1.实例对象p的隐式原型指向它构造函数的显式原型 p.__proto__ = Person.prototype //true
2. 查找属性,如果本身没有,则会去__proto__中查找,也就是构造函数的显式原型中查找,如果构造函数的显式原型中也没有该属性,因为构造函数的显式原型也是对象,也有__proto__,那么会去它的显式原型中查找,一直到null,如果没有则返回undefined
3. p.__proto__.constructor == function Person(){}
4. p.___proto__.__proto__== Object.prototype
5. p.___proto__.__proto__.__proto__== Object.prototype.__proto__ == null
6. 通过__proto__形成原型链而非protrotype
解析实例问题:
在Function和Object的原型分别加上,
Function.prototype.a=1;
Object.prototype.b=2;
a,b属性,p.a和p.b,以及Person.a和Person.b?
分析:遵循一个链式原则,层层往上寻找,直至null
Person.a和Person.b
Person本身是一个Function,可以直接访问到其原型上的b属性,
Person.__proto__ === Function.prototype // true
Person.__proto__.a === Function.prototype.a// true
所以:Person.a = 1
Function.prototype上没找到b,继续向上寻找
Person.__proto__.__proto__===Function.prototype.__proto__ === Object.prototype// true
Person.__proto__.__proto__.b===Object.prototype.b//true
所以:Person.b = 2
同理分析:p.a和p.b; 实例对象p只有__proto__(隐式原型)
p.__proto__ === Person.prototype// true
p.__proto__.__proto__===Person.prototype.__proto__===Object.prototype// true
p.__proto__.__proto__.a===Object.prototype.a// true
p.__proto__.__proto__.b===Object.prototype.b// true
所以:p只能向上逐步获取到Object.prototype的值
p.a=undefined
p.b=2
验证:
总结如下(结合上图更容易理解):
1. 实例对象a只有__proto__(隐式原型),构造函数既有 __proto__(隐式原型)也有prototype(显式原型)
2. __proto__ 和 prototype 都是一个对象,既然是对象,就表示他们也有一个 __proto__
3.实例对象a的隐式原型指向它构造函数的显式原型,指向的意思是恒等于
借鉴:一篇文章让你搞懂原型和原型链(本文转载自【微信公众号:手机电脑双黑客,ID:heikestudio】,经微信公众号授权转载,如需转载与原文作者联系)