沿着A的__proto__这条线查找的同时沿着B的prototype这条线来找,如果两条线能找到同一个引用(对象),那么就返回true。如果找到终点还未重合,则返回false。
再来看我们之前的那个例子
function Foo(){ this.a=1; } Foo.prototype.a=2; Foo.prototype.b=3; var f1 = new Foo; //没有参数的话括号可以省略 console.log(f1.a) //1 console.log(f1.b) // 3
当我们查找f1.a时,因为f1中有这个属性,所以我们得出 f1.a=1;
当我们查找f1.b时,f1中没有这个属性,我们便顺着f1.__proto__这条链去它的构造器的prototype上找,所以我们得出了 f1.b = 3;
当我们查找一个对象的属性时,先在这个对象的私有空间内查找,如果没找到,就顺着对象的__proto__这条链去它的构造器的ptototype上查找,如果还没找到,接着沿__proto__向上查找,直到找到Object.prototype还没有的话,这个值就为undefined,这就是所谓的原型链
列举下网页中的一些相关的原型链
有兴趣的同学可自行通过浏览器控制台看看我们常用的方法都是在哪个类上定义的,比如getElementsByTagName,addEventListener等等
继承
在这里就主要说一下组合继承(call + 原型链)
function Father(){ this.xxx= 80; this.yyy= 100; this.drink = function(){} } Father.prototype.zzz= function(){} var father = new Father; function Son(){ this.aaa = 120; this.singing = function(){} Father.call(this); } Son.prototype = new Father; Son.prototype.constructor = Son; var son = new Son console.dir(son)
这么写有个不好的地方就是:子类私有的属性中有父类私有的属性,子类公有的属性中也有父类私有的属性;
根据我们前边的知识,我们可以这么来改写
function Father(){ this.xxx= 80; this.yyy= 100; this.drink = function(){} } Father.prototype.zzz= function(){} var father = new Father; function Son(){ this.aaa = 120; this.singing = function(){} Father.call(this); //利用call继承了父类的私有属性 } Son.prototype.__proto__ = Father.prototype var son = new Son console.dir(son)
最后来一张思维导图
图片如果放大也看不清的话 下载地址