javaScript中的對象的繼承

借用構造函數實現繼承

function SuperType(){
    this.colors = ["red","blue","green"];
}

function SubType(){
    //在子類構造函數中調用父類構造函數(同時這種方式支持向父類構造函數傳參)
    SuperType.call(this);
    //SuperType.call(this,arg1,arg2)
    //SuperType.apply(this,args)
}

作用:借用構造函數方式是在新的SubType對象上面執行SuperType中定義的初始化代碼,針對在原型中的引用類型,每一個實例都有自己的一個副本(可以清除原型中包含引用類型值的問題)

問題:僅僅是借用構造函數,無法避免構造函數模式存在的問題,方法都是在構造函數中定義,因此函數複用就無從談起了

組合繼承(經典繼承)

這種方式的思想是使用原型實現對原型屬性和方法的繼承,而通過構造函數實現對實例屬性的繼承

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);
    //自己的實例屬性
    this.age = age;
}
//通過原型方式繼承父類
SubType.prototype = new SuperType();
//重寫constructor屬性
SubType.prototype.constructor = SubType;
SubType.ptototype.sayAge = function(){
    alert(this.age);
}

組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優點,是javaScript中最常用的一種繼承模式。

問題:組合繼承會導致父類構造方法被調用兩次,當我們在創建子類原型的時候會調用一次,第二次是我們調用子類構造方法的時候裏面會調用一次。

原型式繼承

藉助原型可以基於已有對象創建新的對象,同時還不必因此創建自定義類型

var person = {
    name:"SC",
    friends:["nix","unix","windows","ubantu"]
}
function object(o){
    //臨時構造函數
    function F(){};
    //繼承
    F.prototype = o;
    return new F();
}
var p1 = object(person);
p1.friends.push("p1's friends");
p1.name = "P1";

var p2 = object(person);
p2.friends.push("p2's friends");
p2.name = "P2";

console.log(p1.name);//P1
console.log(p2.name);//P2
console.log(p1.friends);//["nix", "unix", "windows", "ubantu", "p1's friends", "p2's friends"]
console.log(p2.friends);//["nix", "unix", "windows", "ubantu", "p1's friends", "p2's friends"]

上面的原型方式在ECMScript5中通過新增Object.create()方法規範化了,該方法接收兩個參數,第一個爲用作新對象原型的對象和(可選的)一個新對象定義額外屬性的對象。Object.create()方法是對對象進行一個簡單的克隆,如果對象裏面有引用類型的屬性,那麼只會複製一份引用

問題:原型式繼承同樣沒有解決引用問題

寄生式繼承

寄生式繼承思路與寄生構造函數類似,也就是創建一個僅僅用於封裝繼承過程的函數,該函數內部以某種方式來增強對象,最後再像真正的地是它做了所有的工作一樣返回對象。

//寄生式繼承
function createAnother(original){
    //調用函數創建一個新的對象
    var clone = object(original);
    //以某種方式來增強這個對象
    clone.sayHi = function(){
        alert("HI");
    }
    return clone;
}
//上面的object()函數不是必須的,每一個能夠返回新對象的函數都可以適用這個模式

問題:可以使用寄生繼承來爲對象添加函數,會由於不能做到函數複用而降低效率,這一點會與構造函數模式類似。

寄生組合式繼承

寄生組合式繼承解決組合繼承中兩次調用父類構造函數的問題。寄生組合式繼承,也就是通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。

思路是:不必爲了指定子類的原型而調用超類的構造函數,我們所需要的無非就是超類型原型的一個副本而已,本質上,就是使用寄生繼承來繼承超類原型,然後再將結果指定給子類型的原型


function inheritPrototype(subType,superType){
    //創建對象
    var prototype = object(superType.prototype);
    //增強對象
    prototype.constructor = subType;
    //指定對象
    subType.prototype = prototype;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章