Open HelloChunWei opened 4 years ago
寫得很好! 對TC39和stage的解釋很詳盡. 最近Typescript 5支援了decorator的寫法想說TC39有通過過decorator嗎就闖進來了
@samson-sham 謝謝 XD 原本只是想說留個記錄讓我自己看看,沒想到真的有其他讀者XD
不過目前我自己還在思考 decorator 的使用情境。現在沒有太多的想法
Google 出來第一篇就是這個,笑死
某方面看起來像 Wrapper,我以為 Decorator 已經實裝幾年了,沒想到還沒
前言
最近這幾天重新學習了設計模式,剛好到了裝飾者模式 (Decorator pattern) 在網路上找尋JS的簡單範例時,發現 ES7(ECMAScript2016) 有 decorator 的語法糖~經過一番波折之後發現...... ES7(ECMAScript2016) 根本沒有規範 decorator.
讓我娓娓道來
什麼是裝飾者模式
先稍微介紹一下裝飾者模式,簡單來說,在不影響原本的物件下,動態的新增其他功能,而不動到原本物件的程式碼。舉例:今天我們有個物件是 Person,他會sayHello 以及 sayGoodbye.
但是呢,我想要可以在打招呼或再見時可以揮揮手,可以怎麼做?
第一種做法:
看起來沒有什麼問題,也非常的直覺,但假設我們今天是一個套件的管理者呢?
其他開發者希望可以增加揮揮手的功能,有些人則希望可以增加自定義的打招呼方式,那我們是不是每一次都要新增功能在Person上?每新增一個功能套件就要改一次版。久而久之程式碼可能會更難維護。
所以我們可以利用裝飾者模式:
我們就可以跟用我們的套件開發者說:「你只要符合我們的規定,你可以自定義你想要的動作」
例如: 有人想要每次打招呼都要跳段舞~
簡單的了解裝飾者模式後,我們的故事繼續下去~
上面那段 code 基本上是原生的 Javascirpt 寫法,有沒有更方便,或者更直覺的語法糖呢?
在找資料時,發現這篇文章 Exploring EcmaScript Decorators 作者似乎是在 Google 工作的工程師,而且也是在 medium/google-developers 下發表。
內文有提到 ES7(ECMAScript2016) 中有提供 decorator 的語法糖,有附有簡單的範例,話不多說,馬上試試看吧~
使用 decorator 語法糖
最一開始 decorator 我是用 codepen 去寫範例的(懶得再用babel建置)既然是在 ES7(ECMAScript2016) 的規範下,那codepen 可以用async/await ,那就可以用 decorator 吧?
but!! 實際上不行~嘗試多次之後,決定放棄codepen,改建置一個簡單的專案用babel 去編譯。
若要使用 decorator 得先安裝 babel 套件:(babel/plugin-proposal-decorators)
編譯執行後,確實是可以照著我想的樣子執行。
但在 babel 套件網站看到一段讓我覺得怪怪的文字:
stage 1?? stage 1 代表什麼意思???
後來在 babel/plugin-proposal-decorators 最下面找到了 references。
恩.....稍微看了一下,大致上是 decorator 的用法,不過在該篇文章最上面表示: This has moved to https://github.com/tc39/proposal-decorators
點進去後發現來到了TC39的github頁面。(我是誰?我在哪?我為什麼會在這裡?)
TC39 是什麼?
沒關係,我們坐下來,洗個澡,一個一個的把問題解決。首先,要先知道tc39是什麼?
在找尋資料的時候發現了這文章,裡面有簡易的介紹TC 39這個組織。
tc39 原名為 Technical Committee 39 基本上是為了改進 javascirpt 的組織,裡面的成員大多都是公司(瀏覽器開發商等等.....),ECMAscript 就是他們設計的。
TC39 的流程
該篇文章有提到: 由於ES6發布後花了將近6年才將其標準化 (2019-2015) ,為了避免有類似的情形發生,他們開發了新的流程,保持一年出新的一版,每年新增的內容也不會太多。
流程一共分成五個 stage,從 stage0 到 stage4,到最後的 stage4 之後,就表示新的內容可以加入到 ECMAScript 中。
如果想知道更詳細的流程可以到 The TC39 Process 了解,這裡就不多做說明。
所以我說那個 decorator 呢?
從 TC39 的流程中,我們可以看到關鍵字 stage 2,這跟 proposal-decorators 中是在一樣的階段,所以代表 decorator 的語法糖並沒有在 ES7(ECMAScript2016) 規範中囉?
我到了該年規範中發現該年跟一般開發者比較相關的 feature 是 Array.prototype.includes. (等等!? 所以 async/await 並沒有在 ECMAScript2016 中!?)
從文件中可以得知 decorator 並沒有在 ES7 (ECMAScript2016) 的規範內。
重新整理一次
把疑問都解開之後,我又再一次的回去看那篇文章 Exploring EcmaScript Decorators 再仔細的看一次,發覺該篇作者確實是有說 decorator 的語法糖是在提案階段,例如文章前段的:
以及後半段的:
但如果在實驗階段的話,為什麼他會說 ES2016 Decorators 呢?這讓我很疑惑。
Axel Rauschmayer 也提到: Don’t call them ECMAScript 20xx features 除非是到了stage4,不然不應該把那些還正在提案中的 feature 說是在到某年的規範中,畢竟也是有提案到一半被放棄的例子。在這點上,我是滿認同 Axel Rauschmayer 的觀點。
結論
decorator 並沒有在 ES7 (ECMAScript2016) 的規範內。但可以透過 babel 讓我們先行體驗這語法糖
所以這也可以解釋為何沒辦法很順利的在 codepen 使用。 (或許可以,如果真的可以的話,請告知我,謝謝~)
這一次的經驗算是滿特別的,從一個設計模式延伸到TC39,以及ECMAScript,雖然實務上可能不會用到這些知識,不過把心中的疑惑解開,那感覺也是滿棒的~
而且非常佩服那些貢獻者,要不斷的開會、測試,確認沒問題之後,才會正式標準化,也非常佩服 babel,webpack,nodeJS 的團隊。不斷的讓開發者們可以使用新的規範。
哦對了~~ 剛剛查了一下 TC39 proposals,原來async function 並不是 ES7 (ECMAScript2016) 的標準呀,是 ES8 (ECMAScript2017) 的標準。
後記
後來我又在網路上搜尋 「javascript decorator」 發現有些文章會把他歸類 ES7(ECMAScript2016),有些文章則清楚表示他則是在提案階段。經過這一次經驗後,找資料時最好的方法就是去找原始文件。
在這個例子就是要去看 ECMAScript2016 或者 tc39/proposals 去確認 decorator 是否已經在規範中,還是在提案階段
參考資料: