JS中的6種繼承方法

一、原型的繼承
只需要將子級(jí)的原型對(duì)象設(shè)置為父級(jí)的一個(gè)實(shí)例,加入到原型鏈中即可。

// 繼承原型
cPerson.prototype = new Person(name, age);
// 添加更多方法
cPerson.prototype.getLive = function() {}

缺點(diǎn):
1.來(lái)自原型對(duì)象的引用屬性是所有實(shí)例共享的,原型中的一改則全改
2.創(chuàng)建子類實(shí)例時(shí),無(wú)法向父類構(gòu)造函數(shù)傳參


二、構(gòu)造函數(shù)的繼承
等于是把父類的實(shí)例屬性復(fù)制了一份給子類實(shí)例裝上了(完全沒(méi)有用到原型)
(構(gòu)造函數(shù)的本質(zhì),它其實(shí)是在new內(nèi)部實(shí)現(xiàn)的一個(gè)復(fù)制過(guò)程)
在繼承時(shí)想要的,就是想父級(jí)構(gòu)造函數(shù)中的操作在子級(jí)的構(gòu)造函數(shù)中重現(xiàn)一遍即可。我們可以通過(guò)call方法來(lái)達(dá)到目的。

// 構(gòu)造函數(shù)的繼承function cPerson(name, age, job) {
    Person.call(this, name, age);
    this.job = job;
}

缺點(diǎn):
無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類實(shí)例都持有一個(gè)新的fun函數(shù),太多了就會(huì)影響性能,內(nèi)存爆炸。


三、組合繼承(最常用)
把實(shí)例函數(shù)都放在原型對(duì)象上,以實(shí)現(xiàn)函數(shù)復(fù)用。同時(shí)還要保留借用構(gòu)造函數(shù)方式的優(yōu)點(diǎn),通過(guò)Super.call(this);繼承父類的基本屬性和引用屬性并保留能傳參的優(yōu)點(diǎn);通過(guò)Sub.prototype = new Super();繼承父類函數(shù),實(shí)現(xiàn)函數(shù)復(fù)用

function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();    // 核心

缺點(diǎn): 由于調(diào)用了2次父類的構(gòu)造方法,會(huì)存在一份多余的父類實(shí)例屬性(原因: 第一次SuperType.call(this);語(yǔ)句從父類拷貝了一份父類實(shí)例屬性給子類作為子類的實(shí)例屬性,第二次SubType.prototype = new SuperType();創(chuàng)建父類實(shí)例作為子類原型,此時(shí)這個(gè)父類實(shí)例就又有了一份實(shí)例屬性,但這份會(huì)被第一次拷貝來(lái)的實(shí)例屬性屏蔽掉,所以多余。)


四、寄生組合繼承(最佳方式)
( 對(duì)組合繼承的優(yōu)化)
用beget(Super.prototype);切掉了原型對(duì)象上多余的那份父類實(shí)例屬性

function beget(obj){   // 生孩子函數(shù) beget:龍beget龍,鳳beget鳳。
    var F = function(){};
    F.prototype = obj;
    return new F();  //返回一個(gè)新的構(gòu)造函數(shù)F的實(shí)例
}
function Super(){
    // 只在此處聲明基本屬性和引用屬性
    this.val = 1;
    this.arr = [1];
}
//  在此處聲明函數(shù)
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
var proto = beget(Super.prototype); // 核心
proto.constructor = Sub;            // 核心
Sub.prototype = proto;              // 核心
 
var sub = new Sub();
alert(sub.val);
alert(sub.arr);

五、原型式
用生孩子函數(shù)得到得到一個(gè)“純潔”的新對(duì)象(“純潔”是因?yàn)闆](méi)有實(shí)例屬性),再逐步增強(qiáng)之(填充實(shí)例屬性)
(beget函數(shù)的參數(shù)為父類的一個(gè)實(shí)例化對(duì)象,這個(gè)參數(shù)作為新構(gòu)造函數(shù)的原型)

function beget(obj){   // 生孩子函數(shù) beget:龍beget龍,鳳beget鳳。
    var F = function(){};
    F.prototype = obj;
    return new F();
}
function Super(){
    this.val = 1;
    this.arr = [1];
}
 
// 拿到父類對(duì)象
var sup = new Super();
// 生孩子
var sub = beget(sup);   // 核心
// 增強(qiáng)
sub.attr1 = 1;
sub.attr2 = 2;
//sub.attr3...

六、寄生式
給原型式繼承穿了個(gè)馬甲而已,看起來(lái)更像繼承了(上面介紹的原型式繼承更像是對(duì)象復(fù)制)
注意:beget函數(shù)并不是必須的,換言之,創(chuàng)建新對(duì)象 -> 增強(qiáng) -> 返回該對(duì)象,
這樣的過(guò)程叫寄生式繼承,新對(duì)象是如何創(chuàng)建的并不重要(用beget生的,new出來(lái)的,字面量現(xiàn)做的。。都可以)
(beget函數(shù)的參數(shù)為父類的一個(gè)實(shí)例化對(duì)象,這個(gè)參數(shù)作為新構(gòu)造函數(shù)的原型)
缺點(diǎn):無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用(沒(méi)用到原型,當(dāng)然不行)


相關(guān)參考:

重新理解JS的6種繼承方式

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

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

  • 博客內(nèi)容:什么是面向?qū)ο鬄槭裁匆嫦驅(qū)ο竺嫦驅(qū)ο缶幊痰奶匦院驮瓌t理解對(duì)象屬性創(chuàng)建對(duì)象繼承 什么是面向?qū)ο?面向?qū)ο?..
    _Dot912閱讀 1,536評(píng)論 3 12
  • 我們?cè)趯?duì)象創(chuàng)建模式中討論過(guò),對(duì)象創(chuàng)建的模式就是定義對(duì)象模板的方式。有了模板以后,我們就可以輕松地創(chuàng)建多個(gè)結(jié)構(gòu)相同的...
    csRyan閱讀 1,023評(píng)論 0 7
  • 本章內(nèi)容 理解對(duì)象屬性 理解并創(chuàng)建對(duì)象 理解繼承 面向?qū)ο笳Z(yǔ)言有一個(gè)標(biāo)志,那就是它們都有類的概念,而通過(guò)類可以創(chuàng)建...
    悶油瓶小張閱讀 964評(píng)論 0 1
  • 基于這篇文章的一些名稱約定: 上面的約定應(yīng)該是比較合理的,如果難以理解,可以查看黯羽輕揚(yáng):JS學(xué)習(xí)筆記2_面向?qū)ο?..
    一直玩編程閱讀 614評(píng)論 1 7
  • 這幾天心里頗不寧?kù)o,你總是臉色時(shí)好時(shí)壞,讓我捉摸不透,我們不是說(shuō)好了,要好好的溝通,好好的走下去嗎? 今天你下班后...
    Mr_Zhang2O12閱讀 212評(píng)論 0 0

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