javascript中的繼承-寄生組合式繼承

  前文說過,組合繼承是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

相關文章
相關標籤/搜索