先说说组合继承。最经常使用的继承方式组合继承,其最大的问题是不管在什么状况下,都会调用两次超类型的构造函数:一次是在建立子类原型的时候,另外一次是在子类型构造函数内部。javascript
组合继承是经过原型继承方法和原型属性,构造函数继承实例属性。但子类经过原型也继承了超类型的所有实例属性(方法暂且不说),即超类的实例属性成为子类的原型属性,因此不得不在调用子类构造函数时重写这些属性。也就是说在子类的原型对象上继承来自超类的实例属性彻底是多余的。java
看一个组合继承的例子。函数
function SuperType(name){ this.name = name; this.colors = ['red','blue','green']; } SuperType.prototype.sayName = function(){ alert(this.name); } function SubType(name,age){ SuperType.call(this,name); //第二次调用SuperType() this.age = age; } SubType.prototype = new SuperType(); //第一次调用SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge=function(){ alert(this.age); }; var instance = new SubType('Greg',39); //调用SubType构造函数,重写原型属性 instance.colors.push('black'); //重写原型属性
在第一次调用SuperType构造函数时,SubType.prototype获得两个属性,name和colors(这两个经过原型继承来的属性是多余的)。当建立instance实例调用SubType的构造函数时会再一次调用SuperType的构造函数,这一次又在新对象上建立了实例属性name和colors,也就是重写了原型对象的属性,屏蔽了原型中两个同名属性。this
为了不这种两次调用超类构造函数致使子类原型对象建立了多余属性的缺陷,可使用寄生组合式继承。spa
什么是寄生组合式继承?即经过借用构造函数来继承属性,经过原型链的混成方式来继承方法。prototype
基本思路是:没必要为了指定子类型的原型而调用构造函数,咱们所须要的无非是超类型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,而后将结果指定给子类型的原型。code
基本模式以下:orm
仍是要用以前的 object函数。对象
function object(o){ function F(){}; F.prototype = o; return new F(); }
接着是寄生组合式继承的基本模式。继承
function inheritPrototype(subType,superType){ var prototype = object(superType.prototype); //建立对象 prototype.constructor = subType; //加强对象 subType.prototype = prototype; //指定对象 }
此函数接收两个参数,子类构造函数和超类构造函数。函数内部,第一步建立超类原型对象的一个副本,第二步为副本添加constructor属性,使其指向subType,弥补由于重写原型而失去默认的constructor属性。最后一步,将副本赋值给子类型的原型。整个过程说的简单点,就是将超类原型对象的一个副本复制给子类的原型对象。这样一来就能够避免继承超类的实例属性,也就是避免了在子类原型对象上建立多余的属性了。再举一个例子。
function superType(name){ this.name = namel this.colors = ['red','blue','yellow']; } superType.prototype.sayName = function(){ alert(this.name); } function subType(name, age){ superType.call(this,name); //经过构造函数继承实例属性 this.age = age; }inheritPrototype(subType,superType); //仅调用一次超类构造函数 subtype.prototype.sayAge = function(){ alert(this.age); }
这个例子的高效率体如今它只调用了一次superType构造函数,而且避免了在subType.prototype上建立没必要要的属性。与此同时,原型链还能保持不变,所以能够正常使用instanceof()和isPrototypeOf()。寄生式组合继承是引用类型最理想的继承范式。