面向對象的程序設計之繼承

如下是幾種js中實現繼承的方式方法,它們也是各自有各自的優缺點,選擇哪種根據本身的應用而定,最適合本身的纔是最好的.javascript

經過原型鏈繼承

function SuperType(){
    this.name = 'yahualingfeng';
}

SuperType.prototype.friends = ['David','Bob','Lucy'];
SuperType.prototype.sayName = function(){
    
  alert(this.name);
  
};

function SubType(){
    this.age = 30;    
}

SubType.protoType = new SuperType();//經過原型對象繼承SuperType

var subType1 = new SubType();
var subType2 = new SubType();

subType1.friends.push('Jake');

console.log(subType1.friends); // ['David','Bob','Lucy','Jake']
console.log(subType2.friends); // ['David','Bob','Lucy','Jake']

缺點:java

  • 引用類型的值在原型中會被全部實例共享.
  • 不能向超類的構造函數中傳遞參數

借用構造函數繼承

借用構造函數繼承是將超類(SuperType)全部的屬性和方法都寫在構造函數中,最後在函數(SubType)體內經過call方法調用超類.函數

function SuperType(){
    this.name = 'yuhualingfeng';
    this.friends =['David','Bob','Lucy'];
    this.sayName = function(){
        alert(this.name);
    }
}

function SubType(){
    SuperType.call(this);
}

var subType = new SubType();
subType.sayName();

缺點:方法的定義都存在構造函數中,致使函數沒法被複用.this

組合繼承

組合繼承是原型鏈繼承和構造函數繼承的結合體,結合了兩者的優勢,即實現了函數的複用,也不會致使引用類型值在多個實例中共享.prototype

function SuperType(){
    this.name='yuhualingfeng';
    this.friends=['David','Bob','Lucy'];
}
SuperType.prototype.sayName = function(){
    
    alert(this.name);

};

function SubType(){

    SuperType.call(this);

}

SubType.prototype = new SuperType();

var subType = new SubType();

缺點:code

  • 超類函數被執行了兩次.
  • 超類構造函數SuperType自身的屬性(name,friends)被重複定義,即出如今SubType的構造函數中,也出如今SubType的原型對象中.

原型繼承

原型繼承是繼承自一個對象而不是引用類型.對象

function object(obj){
 function F(){}
 F.prototype = obj;
 return new F();
}

這裏的object方法接收obj對象,並將對象賦值給一個空函數的原型,並返回空函數的實例.繼承

var person = {
 name:'yuhualingfeng',
 friends:['David','Bob','Lucy']
};

var anotherPerson = object(person);
anotherPerson.name = 'Jake';
anotherPerson.friends.push('Marry');

console.log(anotherPerson.friends); //['David','Bob','Lucy','Marry']

console.log(person.friends); //['David','Bob','Lucy','Marry']

若是不想建立構造函數,只想讓一個對象和另外一個對象保持一致的狀況下,原型繼承是徹底能夠勝任的,不過有一點要注意的是,假如繼承的屬性值爲引用類型時,仍是會相互影響的.ip

寄生繼承

寄生繼承是基於原型繼承的基礎上擴展本身的屬性和方法.ci

function createrAnother(obj){
    var clone = object(obj);
    clone.sayHi=function(){
     alert('Hi!');
    }
    return clone;
}

var person = {
    name:'yuhualingfeng'
};

var anotherPerson = createAnother(person);

anohterPerson.sayHi();  // Hi

寄生繼承也是和原型繼承同樣也是繼承對象,併產出對象.

寄生組合繼承

顧名思義,寄生組合繼承是集寄生繼承和組合繼承的結合體,它結合了兩者的優勢.

//繼承Supertype的原型對象
function inheritProtoType(SuperType,SubType){
 
     var prototype = object(SuperType.prototype);
     prototype.constructor = SubType;
     SubType.prototype = prototype;

}

function SuperType(){
    this.name = 'yuhualingfeng';
    this.friends = ['David','Bob','Lucy'];
}

function SubType(){
    ////繼承Supertype的構造函數屬性
    SuperType.call(this);
    this.age = 30;
}

inheritProtoType(SuperType,SubType);

var subType = new SubType();

寄生組合繼承是前面幾種繼承思想碰撞在一塊兒的產物,是執行效率最高也是應用面最廣的.

總結

原型鏈繼承是經過爲原型對象賦值,不足之處爲引用類型值會被多個實例共享,構造函數繼承解決了原型鏈繼承的問題,同時也暴露出新的問題是函數的複用沒法實現,而後咱們結合兩者的優缺點,構造出了組合繼承,組合繼承基本上知足了咱們想要的繼承結果.
考慮到執行的效率,咱們構思出了寄生繼承(基於原型繼承),並將寄生繼承組合繼承結合,最終得出了繼承的最優解決方案'寄生組合繼承.

相關文章
相關標籤/搜索