前文說過,組合繼承是javascript最經常使用的繼承模式,不過,它也有本身的不足:組合繼承不管在什麼狀況下,都會調用兩次父類構造函數,一次是在建立子類原型的時候,另外一次是在子類構造函數內部.子類最終會包含父類對象的所有實例屬性,但咱們不得不在調用子類構造函數時重寫這些屬性.請再看一次組合繼承的例子:javascript
function SuperType(name){ this.name=name; this.friends=["gay1","gay2"]; } SuperType.prototype.sayName=function(){ alert(this.name); }; funciton SubType(name,age){ SuperType.call(this,name); //第二次調用SuperType(); this.age=age; } SubType.prototype=new SuperType(); //第一次調用SuperType() SubType.prototype.sayAge=function(){ alert(this.age); };
在第一次調用SuperType構造函數時,SubType.prototype會獲得兩個屬性:name和friends,他們都是SuperType的實例屬性.只不過如今位於SubType的原型中.當調用SubType構造函數時,又會調用一次SuperType構造函數,這一次又在新對象上建立了實例屬性name和friends.因而,這兩個屬性就屏蔽了原型中的兩個同名屬性.java
結果是,有兩組name和friends屬性,一組在SubType的實例上,一組在SubType的原型上.這就是調用兩次SuperType構造函數的結果.而如今,找到了解決這個問題的方法:寄生組合式繼承.函數
寄生組合式繼承:經過借用構造函數來繼承屬性,經過原型鏈的混成形式來繼承方法.思路:沒必要爲了指定子類的原型而調用父類的構造函數,咱們所須要的無非就是父類原型的一個副本而已.本質上,就是使用寄生式繼承來繼承父類的原型,而後在將結果指定給子類的原型:this
function inheritPrototype(subType,superType){ var prototype=object(superType.prototype); //建立父類原型的一個副本 等同於使用Object.create(superType.prototype) prototype.constructor=subType; //爲副本添加constructor屬性,彌補重寫原型而失去的constructor屬性 subType.prototype=prototype; //將建立的對象(副本)賦值給子類的原型 }
這樣,咱們就能夠經過調用inheritPrototype()函數,替換前面例子中爲子類原型的賦值語句了:spa
function inheritPrototype(subType,superType){ var prototype=Object.create(superType.prototype); //建立父類原型的一個副本 等同於使用Object.create(superType.prototype) prototype.constructor=subType; //爲副本添加constructor屬性,彌補重寫原型而失去的constructor屬性 subType.prototype=prototype; //將建立的對象(副本)賦值給子類的原型 } function SuperType(name){ this.name=name; this.friends=["gay1","gay2"]; } SuperType.prototype.sayName=function(){ alert(this.name); }; function SubType(name,age){ SuperType.call(this,name); //繼承SuperType this.age=age; //擴展出age屬性 } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge=function(){ alert(this.age); };//擴展出sayAge方法 var person1=new SubType("nUll",25); var person2=new SubType("mywei",25); person1.friends.push("gay3"); person1.sayName(); person1.sayAge(); alert(person1.friends); //gay1,gay2,gay3 alert(person2.friends); //gay1,gay2 alert(person1 instanceof SubType); //true alert(person1 instanceof SuperType); //true alert(SubType.prototype.isPrototypeOf(person1)); //true alert(SuperType.prototype.isPrototypeOf(person1)); //true
這個例子的高效率體如今它只調用了一次SuperType構造函數,而且所以避免了在SubType.prototype上建立沒必要要的 多餘的屬性.與此同時,原型鏈還能保持不變.所以,還可以正常使用instanceof 和isPrototypeOf肯定繼承關係.prototype
YUI的YAHOO.lang.extend()方法採用了寄生組合式繼承。code