iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 30
0
Modern Web

跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset系列 第 30

[day29] YDKJS (Prototypes) : Prototype (Delegation pattern) 實踐 Inheritance

  • 分享至 

  • xImage
  •  

prototype 如果 shadow 會怎麼樣?

line 10 :

你直接加一個 ask 方法在 deepJS 上面。

但之前 line 4 又有另一個 ask 方法,
這種狀況就是 shadowing。

順帶一提, line 11 的 this 也要看是誰呼叫的
這邊的例子是 line 14, this 就是 deepJS,
然後又找一次 deepJS ⋯⋯ infinite recursion!

要如何指向正確的目標?

proto

用 donderproto 去增加 property,
其實就是往上一層 prototype chain 增加 property。

line 11 :

this.__proto__.ask 裡面的 this ,此時也是找誰呼叫的
依然是 line 14, this 就是 deepJS,
找 deepJS 裡面的時候,此時 this 卻已經是workshop.prototype (對照前一個無窮迴圈)。

不過 this 還是被帶走了,因為 this 是動態的,要取決於 誰呼叫它

為什麼要 shadowing ?

因為你以前用 class OOP 寫多型,都是這種方法。

那麼,JavaScript 的 繼承建議如何使用?

line 11

Object.create : 創造一個新的 Object ,然後 linked to workshop.prototype

Object.create 可以視為一種 new 的 API,因為做的事情和 new 前兩個步驟一樣:

  1. 創照一個新的 empty object。
  2. link thats object to another object 。

line 16

對於 line 16,就會有這一系列的 linked prototype chain 可以使用。

line 18

先找 JSRecentParts 有沒有 speak 方法可以用,
如果沒有就往上找 anotherWorkshop.prototype 有沒有 speak 方法可以用,
這時候有找到,但是 this 依然還是只看 誰呼叫它
這邊呼叫的是 JSRecentParts ,所以成功完成我們比較習慣的多型,
但是用 JavaScript 的特性完成。

再舉一個例子

找 JSRecentParts 有沒有 ask 方法可以用:

  1. 找 JSRecentParts 自己
  2. 沿著 prototype chain 找 anotherWorkshop.prototype
  3. 沿著 prototype chain 找 Workshop.prototype 找到 ask
  4. 但是 this 還是 JSRecentParts 自己 (this 只看 誰呼叫它

這種感覺就是 JavaScript 很強的地方。

Kyle 總結 繼承

傳統 Class OOP

  1. 一個 Workshop Class,它的實例(instances) 其實是複製原先的方法(程式比較有效率)。

  2. 當你使用 繼承 到新的 AnotherWorkshop ,本質上還是複製。

  3. 所以繼承 AnotherWorkshop 的 JSRecentParts 實例,也是複製。

繼承方向是「從左到右,從上到下」

JavaScript prototype chain

  1. 你有一個 Workshop.prototype 物件 。

a.k.a. 太重要找不到名字命名的物件,希望現在你也有覺得它很重要。

  1. 你創造一個新的物件,然後用 linked 的方式對 Workshop.prototype 產生關聯性。

  2. 你也可以創造 AnotherWorkshop , linked Workshop.prototype。

  3. 也可以產生 JSRecentParts ,但只 linked AnotherWorkshop,
    但 linked 關係不要斷就可以取用 Workshop.prototype 的方法。

繼承方向是「從右到左,從下到上」

JavaScript 一個淺在的問題:

我們使用 Class,
又使用 prototype inheritance (繼承) 的字眼來對使用的功能命名,

但又要和熟悉 Class OOP ,
inheritance OOP 說: 這不是 OOP。

雖然有提到 prototype ,
但歷史上沒有什麼資料來證明這是什麼(Kyle說他查不到來源,為什麼要用這個名字)。

就像是和別人對著蘋果(Class)說 :

「這不是蘋果(Class OOP inheritance),這是紅色的橘子(prototype inheritance)」

這也難怪大家用 Class 都用到黑人問號。
對很多人來說,管你叫 Class OOP inheritance,還是 prototype inheritance,
我以前學過的 inheritance 就是 Class OOP,
你 JavaScript 又做那麼像(故意做那麼像),那就不要怪我用錯。

Why don't class in JavaScript work the way they do in other language?
Kyle: Because the sysyems are completely fundamentally different!

JavaScript inheritance is Delegation pattern

Kyle 認為 JavaScript 就是 Delegation pattern,
然後 Delegation 和 class OOP inheritance 完全是不同的 pattern。

不要把兩個東西混用,才是最好的工具用在最好的地方。

Kyle 也認為 Delegation pattern 的淺力很大,
但可惜都浪費在實踐 class pattern 上,

怎麼認為 Delegation pattern 的淺力很大?
Delegation pattern 可以某種層面上實踐 class pattern ,
但 class pattern 很難實踐 Delegation pattern 。

我個人認為,其實可以,但是基於效能問題,不太常實際運用在專案上。
反而善用 單例模式 Singleton 或是 工廠模式 Factory 就可以解決 class pattern 問題。
應該還是回歸實際,兩個東西是不一樣的,沒人比較涼鞋好還是布鞋好這種問題。


明天才是我的 30 Days !


上一篇
[day28] YDKJS (Prototypes) : Prototype Chain 的 __proto__
下一篇
[day--] YDKJS (infinite) : 沒有結束的一天?
系列文
跟著 YDKJS 作者 Kyle Simpson 打造全新 JavaScript Mindset31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言