2020-01-06:第六章:繼承的擴展(第六章結束)

3.2借用構造函數(shù)

因為原型帶有的引用值問題西剥,開發(fā)人員開始使用借用構造函數(shù)的方法(又被稱為偽造對象或者經(jīng)典繼承)寿弱。它會在子類型構造函數(shù)的內(nèi)部調(diào)用超類型的構造函數(shù)瑞侮。

先來看一個例子:

通過不同方式調(diào)用Child函數(shù)标沪,函數(shù)的執(zhí)行環(huán)境不同

可以知道哆键,在第一次調(diào)用Child()時,其據(jù)以引用的執(zhí)行環(huán)境是全局環(huán)境卦睹,在第二次通過構造函數(shù)調(diào)用Child()時畦戒,其據(jù)以引用的執(zhí)行環(huán)境是a實例,因此this.constructor指向了Child函數(shù)本身(constructor指向的是生成實例的函數(shù)本身)结序。

此時兢交,我們實際上是在(未來將要)新創(chuàng)建的Child實例的環(huán)境下調(diào)用了Father的構造函數(shù),F(xiàn)ather.call(this)在意義上約等于a.Father()笼痹。

這樣一來配喳,就可以在新的對象上執(zhí)行父函數(shù),通過在子類作用環(huán)境中調(diào)用父類構造函數(shù)定義的friend屬性凳干,和直接在實例中定義的friend屬性一致晴裹,都只存在于Child實例中而不存在于任何原型中,避免了繼承所面臨的引用值問題救赐。

1.傳遞參數(shù)

相對于原型鏈而言涧团,借用構造函數(shù)可以在字類型構造函數(shù)中向超類型(也叫父類型)構造函數(shù)傳遞參數(shù)。

實質上是為子類的實例設置屬性

如果為了確保父類寫入屬性時不會覆蓋子類经磅,可以在調(diào)用父類構造函數(shù)之后再為子類設置屬性泌绣。

2.借用構造函數(shù)的問題

構造函數(shù)法無法復用函數(shù)。

但是僅僅借用構造函數(shù)预厌,無法避免構造函數(shù)模式存在的問題:一切都在構造函數(shù)中定義阿迈,函數(shù)復用便無從談起。而且在超超類型的原型中定義方法轧叽,對子類型而言也時不可見的苗沧。子類無法繼承超類的原型中定義的方法,因此這種方式在實際使用中也不經(jīng)常炭晒。

3.3組合繼承(必會)

組合繼承指的是將原型鏈和借用構造函數(shù)兩種方法組合待逞,其思路是:

使用原型鏈實現(xiàn)對原型屬性和方法的繼承。

而通過借用構造函數(shù)來實現(xiàn)對實例屬性的繼承网严。

兼具二者之長

通過組合繼承的方式识樱,我們可以使得a和b兩個Child的實例分別擁有自己的屬性副本,同時共享一套方法震束。這種方式是js中最常用的繼承模式(必會)

3.4原型式繼承

原型式繼承是基于已有的實例創(chuàng)建新對象的方法怜庸。

主要看例子

在object的內(nèi)部,我們首先創(chuàng)建一個臨時性的構造函數(shù)驴一,然后將傳入的實例作為臨時構造函數(shù)的原型休雌,最后返回這個臨時類型的一個實例灶壶。從本質上講肝断,實際上是對傳入的對象做了一次淺拷貝。

基于實例的引用類型

這個方法與之前介紹過的Object.create()方法原理上相同,這個方法接受兩個參數(shù):一個用作新對象原型的對象胸懈,和一個可選的担扑,作為新對象定義額外屬性的對象。在只傳入一個對象時趣钱,create()方法和原型式繼承完全一致涌献。

可以看到,引用類型也是共享的

使用情況:在沒有必要興師動眾的創(chuàng)建構造函數(shù)首有,而只是想創(chuàng)建一個與當前已有對象類似的對象的話燕垃,則可以使用原型式繼承,但是要記住井联,原型式繼承也有引用值共享的問題卜壕。

3.5寄生式繼承

寄生式繼承與寄生構造函數(shù)和工廠模式思想非常類似:創(chuàng)建一個僅用于封裝繼承過程的函數(shù),繼承的過程通過繼承構造函數(shù)實現(xiàn)烙常,并在函數(shù)的內(nèi)部增強對象轴捎,最后再將對象返回,即便繼承的過程是完全通過繼承構造函數(shù)實現(xiàn)的蚕脏。

可以發(fā)現(xiàn)與繼承構造函數(shù)方法唯一的區(qū)別就是把增強對象的過程封裝在了函數(shù)內(nèi)

因此我們可以將寄生式繼承理解為繼承構造函數(shù)方法的擴展侦副。

3.6寄生組合繼承

上文講過,組合繼承是js中最常用的繼承模式驼鞭,但它也有自己的不足秦驯。它的不足在于無論任何情況下,都會調(diào)用兩次超類型(父類型)的構造函數(shù):一次是在創(chuàng)建子類型原型的時候挣棕,一次是在子類型構造函數(shù)內(nèi)部:

調(diào)用兩次父類的構造函數(shù)

雖然子類型最終會包括超類型對象的全部實例屬性汇竭,但我們在子類構造函數(shù)中調(diào)用父類構造函數(shù)(第二次調(diào)用)還是不得不重寫和父類有關的屬性。

按照上面的例子:

第一次調(diào)用父類構造函數(shù)時穴张,Child.prototype獲得兩個屬性friend和parents细燎。他們都將是子類的實例屬性,只不過現(xiàn)在還位于原型中皂甘。

當創(chuàng)建實例時玻驻,我們會在子類構造函數(shù)中再次調(diào)用父類構造函數(shù),這一次又在新實例上創(chuàng)建了實例屬性parents和friend偿枕。

于是璧瞬,新實例上的parents和friend就屏蔽了原型中的同名屬性:我們現(xiàn)在擁有兩組parents和friend屬性:一組在原型上,一組在實例上渐夸。

通過寄生組合繼承的方式嗤锉,可以通過原型鏈的混成形式來繼承方法:即通過借用構造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法墓塌。我們不必為了指定子類型的原型而調(diào)用父類型的構造函數(shù)(消除第一次調(diào)用)瘟忱,我們所需要的只是超類型原型的副本而已奥额。

1(原型式繼承)根據(jù)父類的原型創(chuàng)造一個副本
2(寄生式繼承)將上面得到的副本賦值給子類的原型

這種方式的本質是用寄生式繼承來繼承超類型的原型,然后再將結果指定給子類型的原型:

3(整體全貌)

這個方法的高效體現(xiàn)在他只調(diào)用了一次父類構造函數(shù)访诱。因此避免了在子類原型上創(chuàng)建不必要的垫挨,多余的屬性。

寄生組合繼承毫無疑問是引用各類型最理想的繼承范式触菜。

6.4小結

ECMA支持面向對象編程九榔,但是不使用接口,只支持完全繼承涡相。對象可以在代碼執(zhí)行過程中創(chuàng)建和增強哲泊,因此動態(tài)性極強。常用的有如下幾種創(chuàng)建對象的模式:

①.工廠模式(函數(shù)創(chuàng)建對象催蝗,函數(shù)內(nèi)為對象添加屬性和方法攻旦,然后返回對象)

工廠模式

②.構造函數(shù)模式(創(chuàng)建自定義引用,將新建的實例作為函數(shù)的環(huán)境對象)缺點為函數(shù)不共享(多個實例創(chuàng)建多個函數(shù)對象生逸,而不是多個實例共享一個函數(shù)對象)

構造函數(shù)模式

③.原型模式(用構造函數(shù)的原型來指定應該共享的屬性和方法)牢屋,相比構造函數(shù)模式,多個實例共享同一組方法(來自原型)

原型模式

除此之外槽袄,js主要通過原型鏈實現(xiàn)繼承烙无,原型鏈的核心是將父類型的實例賦值給子類型的原型。這樣子類型可以訪問父類型的所有屬性和方法遍尺。但是原型鏈的繼承會導致多個實例共用一個原型的引用類型屬性截酷,因此不宜單獨使用。

解決這個問題的方法是借用構造函數(shù)乾戏,我們在子類型構造函數(shù)內(nèi)部調(diào)用父類型構造函數(shù)迂苛,這樣就可以做到每個實例的屬性獨立。我們使用最多的就是這種組合繼承的方式鼓择。這種模式的核心是 用原型鏈繼承共享的屬性和方法三幻,再通過借用構造函數(shù)繼承實例獨有的屬性。此外呐能,我們還有幾種擴展的繼承模式:

①.原型式繼承念搬,在想要根據(jù)現(xiàn)有對象復制一個類似的對象時,可以使用這種方式摆出,其本質是對已有對象的淺拷貝:

原型式繼承

②.寄生式繼承朗徊,與原型式繼承相似,僅僅是用一個函數(shù)內(nèi)部封裝了原型式繼承的過程偎漫,并且將對對象的增強也封裝在了函數(shù)內(nèi)部爷恳,最后返回。

寄生式繼承

③.集寄生式繼承和組合繼承的優(yōu)點于一身象踊,式當前最好的温亲,最有效率的繼承方式棚壁。

寄生組合繼承
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铸豁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菊碟,老刑警劉巖节芥,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異逆害,居然都是意外死亡头镊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門魄幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來相艇,“玉大人,你說我怎么就攤上這事纯陨√逞浚” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵翼抠,是天一觀的道長咙轩。 經(jīng)常有香客問我,道長阴颖,這世上最難降的妖魔是什么活喊? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮量愧,結果婚禮上钾菊,老公的妹妹穿的比我還像新娘。我一直安慰自己偎肃,他們只是感情好煞烫,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著累颂,像睡著了一般红竭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上喘落,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天茵宪,我揣著相機與錄音,去河邊找鬼瘦棋。 笑死稀火,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的赌朋。 我是一名探鬼主播凰狞,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼篇裁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赡若?” 一聲冷哼從身側響起达布,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逾冬,沒想到半個月后黍聂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡身腻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年产还,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘀趟。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡脐区,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出她按,到底是詐尸還是另有隱情牛隅,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布酌泰,位于F島的核電站倔叼,受9級特大地震影響,放射性物質發(fā)生泄漏宫莱。R本人自食惡果不足惜丈攒,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望授霸。 院中可真熱鬧巡验,春花似錦、人聲如沸碘耳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辛辨。三九已至捕捂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間斗搞,已是汗流浹背指攒。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留僻焚,地道東北人允悦。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像虑啤,于是被迫代替她去往敵國和親隙弛。 傳聞我的和親對象是個殘疾皇子架馋,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

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