Day41:混入

【書名】:你不知道的JavaScript(上卷)

【作者】:Kyle Simpson

【本書總頁碼】:213

【已讀頁碼】:157

顯式混入

由于 JavaScript 不會自動實現(xiàn) Vehicle到 Car 的復制行為孵奶,所以需要手動實現(xiàn)復制功能叠国。這個功能在許多庫和框架中被稱為extend(..)婿着,但是為了方便理解我們稱之為 mixin(..)兰吟。

現(xiàn)在 Car 中就有了一份 Vehicle 屬性和函數(shù)的副本了套鹅。從技術角度來說,函數(shù)實際上沒有被復制诅病,復制的是函數(shù)引用哪亿。所以,Car 中的屬性 ignition 只是從 Vehicle 中復制過來的對于 ignition() 函數(shù)的引用贤笆。相反蝇棉,屬性 engines 就是直接從 Vehicle 中復制了值 1。

Car 已經(jīng)有了 drive 屬性(函數(shù))芥永,所以這個屬性引用并沒有被 mixin 重寫篡殷,從而保留了Car 中定義的同名屬性,實現(xiàn)了“子類”對“父類”屬性的重寫埋涧。

1. 再談多態(tài)

顯式多態(tài):Vehicle.drive.call( this )板辽。

相對多態(tài):inherited:drive()奇瘦。

JavaScript(在 ES6 之前)并沒有相對多態(tài)的機制。所以劲弦,由于 Car 和Vehicle 中都有 drive() 函數(shù)耳标,為了指明調(diào)用對象,必須使用絕對(而不是相對)引用邑跪。通過名稱顯式指定 Vehicle 對象并調(diào)用它的 drive() 函數(shù)次坡。

但是如果直接執(zhí)行 Vehicle.drive(),函數(shù)調(diào)用中的 this 會被綁定到Vehicle 對象而不是Car 對象画畅。因此砸琅,使用 .call(this)來確保 drive() 在 Car 對象的上下文中執(zhí)行。

如果函數(shù) Car.drive() 的名稱標識符并沒有和 Vehicle.drive() 重疊(或者說“屏蔽”)的話轴踱,就不需要實現(xiàn)方法多態(tài)症脂,因為調(diào)用mixin(..) 時會把函數(shù) Vehicle.drive() 的引用復制到 Car 中,因此可以直接訪問this.drive()淫僻。正是由于存在標識符重疊诱篷,所以必須使用更加復雜的顯式偽多態(tài)方法。

在支持相對多態(tài)的面向類的語言中嘁傀,Car 和 Vehicle 之間的聯(lián)系只在類定義的開頭被創(chuàng)建兴蒸,從而只需要在這一個地方維護兩個類的聯(lián)系。

但是在 JavaScript 中(由于屏蔽)使用顯式偽多態(tài)會在所有需要使用(偽)多態(tài)引用的地方創(chuàng)建一個函數(shù)關聯(lián)细办,這會極大地增加維護成本橙凳。此外,由于顯式偽多態(tài)可以模擬多重繼承笑撞,所以它會進一步增加代碼的復雜度和維護難度岛啸。

使用偽多態(tài)通常會導致代碼變得更加復雜、難以閱讀并且難以維護茴肥,因此應當盡量避免使用顯式偽多態(tài)坚踩,因為這樣做往往得不償失。

2. 混合復制

分析一下 mixin(..) 的工作原理瓤狐。它會遍歷 sourceObj的屬性瞬铸,如果在 targetObj沒有這個屬性就會進行復制。由于是在目標對象初始化之后才進行復制础锐,因此一定要小心不要覆蓋目標對象的原有屬性嗓节。

如果是先進行復制然后對 Car 進行特殊化的話,就可以跳過存在性檢查皆警。不過這種方法并不好用并且效率更低拦宣,所以不如第一種方法常用:

這兩種方法都可以把不重疊的內(nèi)容從 Vehicle 中顯性復制到 Car 中。

復制操作完成后,Car 就和 Vehicle 分離了鸵隧,向 Car 中添加屬性不會影響 Vehicle绸罗,反之亦然。

由于兩個對象引用的是同一個函數(shù)豆瘫,因此這種復制(或者說混入)實際上并不能完全模擬面向類的語言中的復制珊蟀。

JavaScript 中的函數(shù)無法(用標準、可靠的方法)真正地復制靡羡,所以只能復制對共享函數(shù)對象的引用系洛。如果修改了共享的函數(shù)對象(比如ignition())俊性,比如添加了一個屬性略步,那 Vehicle 和 Car 都會受到影響。

如果你目標對象中顯式混入超過一個對象定页,就可以部分模仿多重繼承行為趟薄,但是仍沒有直接的方式來處理函數(shù)和屬性的同名問題。

一定要注意典徊,只在能夠提高代碼可讀性的前提下使用顯式混入杭煎,避免使用增加代碼理解難度或者讓對象關系更加復雜的模式。

3. 寄生繼承

顯式混入模式的一種變體被稱為“寄生繼承”卒落,它既是顯式的又是隱式的羡铲,主要推廣者是Douglas Crockford。

下面是它的工作原理:

調(diào)用 new Car() 時會創(chuàng)建一個新對象并綁定到 Car 的 this 上儡毕。但是因為沒有使用這個對象而是返回了我們自己的 car 對象也切,所以最初被創(chuàng)建的這個對象會被丟棄,因此可以不使用 new 關鍵字調(diào)用 Car()腰湾。

這樣做得到的結(jié)果是一樣的雷恃,但是可以避免創(chuàng)建并丟棄多余的對象。

隱式引入

通過在構(gòu)造函數(shù)調(diào)用或者方法調(diào)用中使用 Something.cool.call( this )费坊,實際上“借用”了函數(shù) Something.cool() 并在 Another 的上下文中調(diào)用了它倒槐。最終的結(jié)果是 Something.cool() 中的賦值操作都會應用在 Another 對象上而不是Something 對象上。

因此附井,把 Something 的行為“混入”到了 Another 中讨越。

雖然這類技術利用了 this 的重新綁定功能,但是 Something.cool.call( this ) 仍然無法變成相對(而且更靈活的)引用永毅,所以使用時千萬要小心把跨。通常來說,盡量避免使用這樣的結(jié)構(gòu)卷雕,以保證代碼的整潔和可維護性节猿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滨嘱,更是在濱河造成了極大的恐慌峰鄙,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件太雨,死亡現(xiàn)場離奇詭異吟榴,居然都是意外死亡,警方通過查閱死者的電腦和手機囊扳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門吩翻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锥咸,你說我怎么就攤上這事狭瞎。” “怎么了搏予?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵熊锭,是天一觀的道長。 經(jīng)常有香客問我雪侥,道長碗殷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任速缨,我火速辦了婚禮锌妻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旬牲。我一直安慰自己仿粹,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布引谜。 她就那樣靜靜地躺著牍陌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪员咽。 梳的紋絲不亂的頭發(fā)上毒涧,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音贝室,去河邊找鬼契讲。 笑死,一個胖子當著我的面吹牛滑频,可吹牛的內(nèi)容都是我干的捡偏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼峡迷,長吁一口氣:“原來是場噩夢啊……” “哼银伟!你這毒婦竟也來了你虹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤彤避,失蹤者是張志新(化名)和其女友劉穎傅物,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體琉预,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡董饰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了圆米。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卒暂。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖娄帖,靈堂內(nèi)的尸體忽然破棺而出也祠,到底是詐尸還是另有隱情,我是刑警寧澤块茁,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布齿坷,位于F島的核電站,受9級特大地震影響数焊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜崎场,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一佩耳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谭跨,春花似錦干厚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至谆扎,卻和暖如春挂捅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堂湖。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工闲先, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人无蜂。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓伺糠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斥季。 傳聞我的和親對象是個殘疾皇子训桶,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

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