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.於是,這兩個屬性就屏蔽了原型中的兩個同名屬性.

  結果是,有兩組name和friends屬性,一組在SubType的實例上,一組在SubType的原型上.這就是調用兩次SuperType構造函數的結果.而現在,找到了解決這個問題的方法:寄生組合式繼承.

  寄生組合式繼承:通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法.思路:不必為了指定子類的原型而調用父類的構造函數,我們所需要的無非就是父類原型的一個副本而已.本質上,就是使用寄生式繼承來繼承父類的原型,然后在將結果指定給子類的原型:

function inheritPrototype(subType,superType){
      var prototype=object(superType.prototype); //創建父類原型的一個副本 等同於使用Object.create(superType.prototype)
      prototype.constructor=subType;   //為副本添加constructor屬性,彌補重寫原型而失去的constructor屬性
      subType.prototype=prototype; //將創建的對象(副本)賦值給子類的原型
}

  這樣,我們就可以通過調用inheritPrototype()函數,替換前面例子中為子類原型的賦值語句了:

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確定繼承關系.

     YUI的YAHOO.lang.extend()方法采用了寄生組合式繼承。

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM