使用构造函数new出来的对象是该类的实例,该实例的__proto__属性指向原型对象,该构造函数的prototype属性也指向原型对象,该原型对象的__proto__指向他继承的原型对象。
每个原型对象的__proto__属性指向其继承的原型对象(父类构造函数的prototype属性)。构造函数的prototype指向原型对象,原型对象有constructor,__proto__两个属性,constructor指向构造函数,__proto__指向该原型对象的原型对象。
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>原型链</title> </head> <body> </body> <script> function Parent() { this.name="parent"; } Parent.prototype.say=function () { console.log("say"); } function Child() { Parent.call(this); this.type="Child"; } Child.prototype=Object.create(Parent.prototype); Child.prototype.constructor=Child var p=new Parent(),c=new Child(); console.log(p,c); </script> </html>
在上述代码中我们写了一个Parent类和一个Child类,Child类继承自Parent类,然后分别new了一个p实例(p=new Parent()),c实例(c=new Child())。
1.Parent叫构造函数,我们一般也把这个类叫Parent类。
2.p叫Parent类的实例。
3.我们可以看出Parent.prototype===p.__proto__的结果为true,Parent.prototype和p.__proto__是严格相等的,他们的指向就叫原型对象。
4.一个实例的构造函数是严格等于他的原型对象的构造函数(c.constructor===Child.prototype.constructor的结果为true)
5.原型对象也是对象是对象就具有__proto__属性,特别的Object对象的原型对象的__proto__属性为空。
6.所有对象的在原型链上最终都指向Object.prototype,而Object不继承自任何对象,所以他的原型对象没有原型对象(Object.prototype.__proto__===null)。
7.实例c的原型对象为c.__proto__,c.__proto__的原型对象为c.__proto__.__proto__也就是Parent.prototype(c.__proto__.__proto__===Parent.prototype结果为true),
c.__proto__.__proto__的原型对象是c.__proto__.__proto__.__proto__即Object.prototype(c.__proto__.__proto__.__proto__===Object.prototype的结果为true),
我们可以发现我们可以通过__proto__属性一直向上查找原型对象,就像所有原型对象绑定在一条链子上,我们可以顺这链子向上查找,这就是原型链!
instanceof运算
instanceof运算就是顺着原型链进行查找,c instanceof Object的运算过程就是先c找c的原型对象c.__proto__,他不等于Object.prototype,所以又找c.__proto__.__proto__,这个还不等于Object.prototype,再找c.__proto__.__proto__.__proto__,这个等于Object.prototype,最后结果返回true。如果在这个查找过程中,原型链上没有一个原型对象与之相等就返回false。
根据这种查找方式c instanceof Child,c instanceof Parent的结果都为true,因为Child和Parent的原型对象都在原型链上。如图
可以看出如果用instanceof来判断一个实例所属的类可能会出错,那么我们用什么方法来判断一个实例具体属于哪个类呢?
注意不同的类的构造函数是不同的,所以我们可以根据constructor属性来进行判断。
c.constructor===Child为true(注意Child指的是构造函数,我们一般也把Child叫Child类),c.constructor===Child.prototype.constructor为true(上面第4条),c.constructor===Parent为false,如图