3分鐘徹底理解,js繼承的6種方式

前言:了解熊師傅的朋友都知道,百度能查的到東西絕對不會提及太多,但是如果能按照思路仔細揣摩相信你一定不會后悔的,接下來開始我的表演。

三分鐘徹悟?哈哈哈。。。
原型鏈自不必說是js前期最晦澀難懂的地方,也是基礎中的基礎,是每一位前端必須有所了解的。

別怕,熊師傅帶你來干 ^ . ^

一.原型鏈繼承

        function aaa (name) {
            this.name = name;
        }
        aaa.prototype.getName = function () {
            return this.name;
        }
        function bbb (name) {
        }
        bbb.prototype = new aaa(‘我是哈哈’);

核心代碼: bbb.prototype = new aaa()
將bbb的原型指向aaa的實例,aaa的屬性和原型方法都將掛載到bbb的原型下面。
缺點:
1.bbb無法給aaa(父類)的構造函數(shù)傳遞參數(shù) (無法繼承構造函數(shù))
2.如果bbb的構造函數(shù)也有name屬性,依然會在原型上繼承aaa的name屬性,造成內(nèi)存浪費

二.借用構造函數(shù)繼承

        function aaa () {
            this.name = name;
        }
        aaa.prototype.getName = function () {
            return this.name;
        }
        
        function bbb (name, age) {
            aaa.apply(this, name);
            this.age = age;
        }
        
        var oBBB = new bbb();

核心代碼: aaa.apply(this, name)
在new bbb() 的 時候調(diào)用aaa,借用aaa的構造函數(shù)。
缺點:
1.無法做到函數(shù)復用(說白了,沒有prototype)

三.組合繼承

        function aaa () {
            this.name = name;
        }
        aaa.prototype.getName = function () {
            return this.name;
        }
        
        function bbb (name, age) {
            aaa.apply(this, name);
            this.age = age;
        }
        
        bbb.prototype = new aaa();
        
        var oBBB = new bbb();

什么是組合繼承?
說白了,就是把前面兩種繼承方式結合起來
核心代碼:
aaa.apply(this, name);
bbb.prototype = new aaa();
思路:bbb通過call借用aaa的構造函數(shù),并將aaa的屬性和原型方法掛載在自己的原型上面。
缺點:
1.依然會造成內(nèi)存浪費,會把aaa的屬性也寫到bbb的原型上面去。

四.原型式繼承

先好好揣摩下這個東西

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

那么這種模式怎么繼承呢?

var aaa = {
    name: 'xxx',
    age: '18',
}

var aaa1 = object(aaa);
var aaa2 = object(aaa);

很顯然aaa1和aaa2的原型上面都會有name和age屬性。
當然缺點也很明顯了:
1.構造函數(shù)和prototype不分,所有實例的原型引用一致,容易造成重寫,和原型鏈繼承的缺點一樣

五.寄生式繼承

說白了,對原型式繼承做了一次改造。先看看如下東西:

function createAnother (obj) {
   var clone = object(obj);
    clone.sayHi = function() {
        alert('hi');
    }
    return clone;
}

var aaa = {
    name: '111',
    age: '2',
};

var aaa1 = createAnother(aaa);

缺點:
1.構造函數(shù)無法復用,也無法接受參數(shù)。(其實有改造空間,把createAnother通過閉包再封裝一層,不過個人不推薦再改造)

六.寄生組合式繼承

堪稱最完美的方式:

// 這個命名牛逼不?  in her it ,老鐵,意會 ^.^
function inherit (sub, sup) {
    var prototype = object(sup.prototype);
    prototype.constructor = sub;
    sub.prototype = prototype;
}

function aaa (name) {
    this.name = name;
}
aaa.prototype.getName = function () {
    alert('111');
}

function bbb (name, age) {
    aaa.call(this, name);
    this.age = age;
}
inherit(bbb, aaa);
bbb.prototype.xixi = function() {
    alert('xixi');
}

到這里基本上解決了所有的問題,perfect。具體的工作原理,前5種繼承方式如果認真研究過一遍了,基本上無需再解釋,若看不懂回過頭來再溫習一遍,熊師傅對于這一塊也是來回研究了十來遍才咯知一二。

但是。
熊師傅對于第六種繼承方式提出一些大家可能會有的疑惑。

1.不是一樣子類繼承父類之后,父類的prototype依然會共享,同一個引用依然會改變父類的原型呀?
2.inherit有什么意義? 和  sub.prototype = sup.prototype有什么區(qū)別?為什么非要通過object方法?

說實話,作者在這里也琢磨了一段時間,算是有一些自己的見解。如有不對,歡迎指正

1.好好想一想我們?yōu)槭裁匆^承?不就是為了復用嗎?如果不是同一個引用,那繼承又有什么意義?(是不是有點恍然大悟的意思^.^)
2.這里通過inherit會重新指正子類sub的構造函數(shù),如果簡單的 sub.prototype = sup.prototype, sub.prototype.constructor = sub 會影響父類sup.

ps:喜歡的朋友別忘記支持一下作者喲^ . ^

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

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

  • 1、構造函數(shù)模式 [url=]file:///C:/Users/i037145/AppData/Local/Tem...
    橫沖直撞666閱讀 937評論 0 0
  • 本章內(nèi)容 理解對象屬性 理解并創(chuàng)建對象 理解繼承 面向?qū)ο笳Z言有一個標志,那就是它們都有類的概念,而通過類可以創(chuàng)建...
    悶油瓶小張閱讀 972評論 0 1
  • 博客內(nèi)容:什么是面向?qū)ο鬄槭裁匆嫦驅(qū)ο竺嫦驅(qū)ο缶幊痰奶匦院驮瓌t理解對象屬性創(chuàng)建對象繼承 什么是面向?qū)ο?面向?qū)ο?..
    _Dot912閱讀 1,545評論 3 12
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 8,140評論 2 17
  • 第九章 在黑色高中的草地上幽幽手里捧著一束玫瑰,手中拿著一張卡片,而眼淚不停的往下落下來, 幽: 離開你八年了,在...
    你懂的黑色閱讀 317評論 1 0

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