js中的繼承總結(jié)

背景

好久都沒有寫原生的js了。突然發(fā)現(xiàn)自己對一些基礎(chǔ)概念有些生疏了,故以紅寶書為基礎(chǔ),總結(jié)下相關(guān)的基礎(chǔ)知識。

原型鏈

js中的繼承主要通過原型鏈來實現(xiàn)。首先來使用原型鏈的基本原理實現(xiàn)一個繼承。

function SuperType() {
    this.property = true;
}

SuperType.prototype.getSuperValue = function() {
    return this.property;
}

function SubType() {
    this.subproperty = false;
}

SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function() {
    return this.subproperty;
}

var instance = new SubType();
原型鏈

但是原型鏈實現(xiàn)的繼承也存在一些問題,當(dāng)父類中存在引用類型的值時會被所有子類所共享。同時在創(chuàng)建子類實例時,不能向父類的構(gòu)造函數(shù)中傳遞參數(shù)。

借用構(gòu)造函數(shù)

為了解決引用類型被所有子類所共享的情況,我們可以在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù),從而達(dá)到每個實例都有自己的屬性。同時我們也解決了子類不能向超類穿參的問題。

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

function SubType() {
    SuperType.call(this, 'test');
}

當(dāng)然這種方式也有明顯的缺點,我們的方法如果都定義在構(gòu)造函數(shù)中的話就沒法進(jìn)行函數(shù)的復(fù)用了。

組合繼承

其結(jié)合了上述兩種繼承方式的優(yōu)點,使用原型鏈來實現(xiàn)原型的屬性和方法的繼承,使用借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。

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

SuperType.prototype.sayName = function() {
    alert(this.name);
};

// 繼承屬性
function SubType() {
    SuperType.call(this, 'test');
}

//繼承方法
SubType.prototype = new SuperType();

SubType.prototype.sayAge = function() {
    alert(this.name);
}

這種方式存在的問題在于會調(diào)用兩次超類的構(gòu)造函數(shù),這使得我們有兩份屬性。

原型式繼承

借助原型基于已有對象創(chuàng)建新對象,同時不必創(chuàng)建自定義的類型

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

寄生式繼承

function createAnother(o) {
    var clone = object(o);
    //增強(qiáng)這個對象
    clone.say = function() {};
    return clone;
}

寄生組合式繼承

這種方式主要解決了組合繼承會調(diào)用兩次超類的問題。其主要思路是:不必為了指定子類的原型而調(diào)用超類的構(gòu)造函數(shù),我們需要的僅僅只是超類的原型。

function inheritPrototype(subType, superType) {
    var prototype = object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}

這種方式避免了在原型上創(chuàng)造不必要的屬性。

最后附上一個完整的寄生組合式繼承

function extend() {
    if (typeof o !== 'function') {
        throw "參數(shù)錯誤";
    }
    
    o = o || {};
    var supr = o, proto,
        supro = supr && supr.prototype || {};

    function fn() {
        supr.apply(this, arguments);
    };

    proto = (function(fn, o) {
        function Foo() {this.constructor = fn};
        Foo.prototype = o;
        return (fn.prototype = new Foo());
    })(fn, supro);

    return fn;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容