JS - 實(shí)現(xiàn)繼承的幾種方法

許多OO語言都支持兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承板惑。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法蛀缝。因?yàn)镋CMAScript中函數(shù)無法簽名刘莹,所以不支持接口繼承阎毅,只支持實(shí)現(xiàn)繼承,而實(shí)際上實(shí)現(xiàn)繼承主要依靠原型鏈實(shí)現(xiàn)点弯;

1扇调、原型鏈繼承

將原型鏈作為實(shí)現(xiàn)繼承的主要方法,其基本思想是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法蒲拉。簡單回顧一下構(gòu)造函數(shù)肃拜、原型和實(shí)例的關(guān)系:每一個構(gòu)造函數(shù)都有一個原型對象,原型對象都包含一個指向構(gòu)造函數(shù)的指針雌团,而實(shí)例都包含一個指向原型對象的內(nèi)部指針燃领。

實(shí)現(xiàn)原型鏈有一種基本模式,代碼大概如下:

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

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

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

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

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

var instance = new SubType();  
console.log(instance.getSuperValue());  

特點(diǎn):
● 非常純粹的繼承關(guān)系锦援,實(shí)例是子類的實(shí)例猛蔽,也是父類的實(shí)例
● 父類新增原型方法/原型屬性,子類都能訪問到
● 簡單,易于實(shí)現(xiàn)

缺點(diǎn):
● 要想為子類新增屬性和方法曼库,必須要在new SuperType()這樣的語句之后執(zhí)行区岗,不能放到構(gòu)造器中
● 無法實(shí)現(xiàn)多繼承
● 來自原型對象的引用屬性是所有實(shí)例共享的
● 創(chuàng)建子類實(shí)例時,無法向父類構(gòu)造函數(shù)傳參

2毁枯、借用構(gòu)造函數(shù)

在解決原型中包含引用類型值所帶來問題的過程中慈缔,開發(fā)人員開始使用一種叫做借用構(gòu)造函數(shù)的技術(shù)。這種技術(shù)的基本思想是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)种玛。函數(shù)只是在特定環(huán)境中執(zhí)行代碼的對象藐鹤,因此通過使用apply()和call()方法也可以在新創(chuàng)建的對象上執(zhí)行構(gòu)造函數(shù)。

function SuperType(){  
    this.colors = ["red","blue","green"];  
}  
  
function SubType(){  
    //繼承了SuperType  
    SuperType.call(this);  
}  
  
var instance1 = new SubType();  
instance1.colors.push("yellow");  
console.log(instance1.colors);  
  
var instance2 = new SubType();  
console.log(instance2.colors);   

通過使用apply()和call()方法赂韵,我們實(shí)際上是在新創(chuàng)建的SubType實(shí)例的環(huán)境下調(diào)用了SuperType構(gòu)造函數(shù)娱节。這樣一來,就會在新SubType對象上執(zhí)行SuperType()函數(shù)中定義的所有對象初始化代碼祭示。這樣的話肄满,SubType的每個實(shí)例就都會具有自己的colors屬性的副本。
相對于原型鏈而言质涛,借用構(gòu)造函數(shù)有一個很大的優(yōu)勢稠歉,即可以在子類型構(gòu)造函數(shù)中向超類型構(gòu)造函數(shù)傳遞參數(shù)。如下所示:

function SuperType(name){  
    this.name = name;  
}  
  
function SubType(){  
    //繼承了SuperType  
    SuperType.call(this,"Wendy");  
    //實(shí)例屬性  
    this.age = 20;  
}  
  
var instance1 = new SubType();  
console.log(instance1.name);//“Wendy”  
console.log(instance1.age);//20  

特點(diǎn):
● 解決了1中蹂窖,子類實(shí)例共享父類引用屬性的問題
● 創(chuàng)建子類實(shí)例時轧抗,可以向父類傳遞參數(shù)
● 可以實(shí)現(xiàn)多繼承(call多個父類對象)

缺點(diǎn):
● 實(shí)例并不是父類的實(shí)例,只是子類的實(shí)例
● 只能繼承父類的實(shí)例屬性和方法瞬测,不能繼承原型屬性/方法
● 無法實(shí)現(xiàn)函數(shù)復(fù)用,每個子類都有父類實(shí)例函數(shù)的副本纠炮,影響性能

3月趟、組合繼承

組合繼承指的是將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合,從而發(fā)揮二者之長的一種繼承模式恢口。主要思想:使用原型鏈實(shí)現(xiàn)對原型屬性和方法的繼承孝宗,然后通過借用函數(shù)來實(shí)現(xiàn)對實(shí)例屬性的繼承。這樣耕肩,即通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用因妇,又能夠保證每個實(shí)例都有它自己的屬性。

function SuperType(name){  
    this.name = name;  
    this.colors = ["red","blur","green"];  
}  
  
SuperType.prototype.sayName = function(){  
    console.log(this.name);  
}  
  
function SubType(name,age){  
    //繼承屬性  
    SuperType.call(this,name);  
    this.age = age;  
}  
  
//繼承方法  
SubType.prototype = new SuperType();  
SubType.prototype.constructor = SubType;  
SubType.prototype.sayAge = function(){  
    console.log(this.age);  
};  
  
var instance1 = new SubType("Wendy",20);  
instance1.colors.push("yellow");  
console.log(instance1.colors); //[ 'red', 'blur', 'green', 'yellow' ]  
instance1.sayName(); //Wendy  
instance1.sayAge(); //20  
  
var instance2 = new SubType("Kitty",18);   
console.log(instance2.colors); //[ 'red', 'blur', 'green' ]  
instance2.sayName(); //Kitty  
instance2.sayAge(); //18  

特點(diǎn):
● 彌補(bǔ)了方式2的缺陷猿诸,可以繼承實(shí)例屬性/方法婚被,也可以繼承原型屬性/方法
● 既是子類的實(shí)例,也是父類的實(shí)例
● 不存在引用屬性共享問題
● 可傳參
● 函數(shù)可復(fù)用

缺點(diǎn):
● 調(diào)用了兩次父類構(gòu)造函數(shù)梳虽,生成了兩份實(shí)例(子類實(shí)例將子類原型上的那份屏蔽了)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末址芯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谷炸,老刑警劉巖北专,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異旬陡,居然都是意外死亡拓颓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門描孟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來录粱,“玉大人,你說我怎么就攤上這事画拾∩斗保” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵青抛,是天一觀的道長旗闽。 經(jīng)常有香客問我,道長蜜另,這世上最難降的妖魔是什么适室? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮举瑰,結(jié)果婚禮上捣辆,老公的妹妹穿的比我還像新娘。我一直安慰自己此迅,他們只是感情好汽畴,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耸序,像睡著了一般忍些。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坎怪,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天罢坝,我揣著相機(jī)與錄音,去河邊找鬼搅窿。 笑死嘁酿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的男应。 我是一名探鬼主播闹司,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼殉了!你這毒婦竟也來了开仰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎众弓,沒想到半個月后恩溅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谓娃,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年脚乡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滨达。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡奶稠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捡遍,到底是詐尸還是另有隱情锌订,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布画株,位于F島的核電站辆飘,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏谓传。R本人自食惡果不足惜蜈项,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望续挟。 院中可真熱鬧紧卒,春花似錦、人聲如沸诗祸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贬媒。三九已至聋亡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間际乘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工漂佩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脖含,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓投蝉,卻偏偏與公主長得像养葵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瘩缆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容