JSDC 2021 前導活動 | ECMAScript 關鍵 30 天 | Are you ready? ES2022!
前言
ECMAScript 原本是不定期地釋出版本,但因應提案的踴躍和開發需求的迫切,所以從 ES2015 後就改為一年一修。也就是說每年都會有新的語法標準出現,讓開發者可以使用更簡潔彈性的語法撰寫,或是實現更強大的功能。
接下來整理預計會在 ES2022 釋出的提案,以簡單的說明加上清楚的程式範例,快速了解起手式💪
ECMAScript 提案五階段
一個想法出來到納入提案,接著成為修訂標準,通常會經歷以下 5 個階段-
Stage | 說明 |
---|---|
0 | 由 TC-39 的成員或其他人提出後,委員會沒有否決的討論或想法 |
1 | 正式成為提案,需有具體語法和描述,部分會有Polyfill的實現 |
2 | 可能有相關的運作環境或編譯器提供實驗性的功能實現 |
3 | 成為候選提案,部分運作環境或編譯器提供原生支援 |
4 | 通過至少兩個驗收測試,等待下版釋出時成為修訂內容 |
今天要講的語法,都是已經進到 finished,也就是 Stage 4 階段的提案。有興趣的話,可以前往 TC-39 的 GitHub 看相關整理。有趣的是,在這裡不僅可以看到語法的開發動機和具體描述,也能看到在提案推進的過程中,開發者與委員們的討論紀錄,可以更進一步地了解標準推出的始末。
正規表達式
先簡單複習一下。正規表達式主要有以下三種組成-
- 以指定的文字加上特殊字元組成匹配的句法。
- 由兩個雙斜線(/)包覆匹配的句法。
- 後面可以選擇性地加上一個或多個旗標,設定全域的查找規則。
其中旗標的部分,一個 RegExp 物件會針對旗標提供實體屬性來查詢。透過取得屬性值,就可以知道這個正規表達式有沒有設定對應的旗標。
Stage | 對應屬性 | 說明 |
---|---|---|
d | hasIndices | 回傳每個匹配內容的起始&下次要開始檢索的索引陣列 ( [startIndex, endIndex+1] ) |
有加上 d
旗標的正規表達式,在執行匹配相關的操作,例如 exec
時,可以多回傳一個 indices
屬性。這個屬性會包含匹配內容的起始索引,以及結束索引加 1,也就是視為下次要開始檢索的索引。
目前最新版本的 Chrome 還有Node.js中可以運作,有興趣的話可以嘗試看看。
1 | const myRegexp = /\w*.o\w+/dgi; // 找出中間有 o 的單字 |
具有索引的標準內建物件
常見的這類物件有字串跟陣列。那麼在 ES2022 推出了什麼相關語法呢?
indexable.at(index)
用途跟使用字面值取得元素的方式類似,透過索引的傳入來獲得元素。不過索引值在負整數跟浮點數時,跟字面值的回傳結果會不一樣。可以看一嚇得比較表-
取得元素的方式 | 負整數 | 浮點數 |
---|---|---|
indexable[index] |
undefined |
undefined |
indexable.at(index) |
後面從 -1 開始算 | 無條件捨去後,再由正負數決定查找方向 |
目前最新版本的 Chrome 可以運作,有興趣的話可以嘗試看看。
1 | const myArray = [0, 1, 2, 3]; |
物件
Object.hasOwn(target, propName)
用來檢查目標物件有沒有屬性。那跟目前習慣使用的 hasOwnProperty
有什麼不一樣呢?
假設以 Object.create(null)
建立了空物件,然後新增一些屬性後,我們想檢查這個物件有沒有特定屬性。可是物件的原型指向了 null
,所以就無法使用實體方法 hasOwnProperty
,除非要直接呼叫 Object.prototype.hasOwnProperty
加上 call
方法來達到這個目的。不過這樣的寫法太冗長了。因此 ES2022 就在 Object
底下新增這個靜態方法,成為語法糖。
目前最新版本的 Chrome 可以運作,有興趣的話可以嘗試看看。
1 | // before |
類別
類別的相關語法在 ES2022 中占了蠻大一部分的內容。其中可以把這些修訂分類為-
- 擴充靜態關鍵字(static)的使用
- 正式支援私有(private)的機制
靜態方法與成員(Static methods and fields)
在 ES2015 時提出的 static
關鍵字,只能做為公開靜態方法的前綴字。不過在 ES2022 後,static
關鍵字的應用範圍更廣泛了。無論是屬性或方法,公開或私有,只要在名稱前加上前綴字,就能表示為靜態。
目前最新版本的 Chrome 可以運作,有興趣的話可以嘗試看看。
1 | class Inbody { |
靜態初始化區塊(Static initialization blocks)
類別初始化時,有些靜態成員需要透過流程控制設定初始值的話,通常只能在類別建立後,把相關的初始流程放在之後。在程式的語意上會像是兩個獨立的區塊拼在一起,規模越複雜的話,就會降低維護性。
1 | class APILibrary { |
ES2022後,類別中只要使用 static
關鍵字加上大括號({ }
),就能包覆靜態成員的初始流程。這樣做還有個好處是,流程中需要存取類別的私有成員時,可以直接取用,而不用再撰寫額外存取器方法來封裝,寫法上算是優雅很多。
1 | class APILibrary { |
定義私有方法與成員(Private methods and fields)
成為私有成員,表示只有內部可以使用,外部如果嘗試存取或呼叫的話,就會回傳 undefined
或錯誤提示。這樣做可以保護成員不會被外部任意修改,或設定只有內部可以操作的方法等。
在 ES2022 後,正式把 #
作為私有成員的前綴字。像是上面的範例程式-static #defaultRoot = 'myroot/api';
,defaultRoot
屬性就是一種私有屬性。
需要注意的是,不只是宣告,在呼叫方法或存取屬性時也需要冠上這個前綴字。更多有關私有方法與成員的範例程式與說明,可以參考我即將上市的書-ECMAScript關鍵30天。
頂層的 await
await
跟 async
的語法是非同步處理的語法糖。只要函式中有 await
的關鍵字出現,就一定要在該函式名稱的前面加 async
的前綴字。在 ES2022 後,可以允許在需要非同步的地方加上 await
就好,不需使用async函式封裝,提升了撰寫非同步的彈性與簡潔性。
1 | // case 1 |
Babel
如果有在專案中使用 Babel,並且設定 @babel/preset-env
這個 preset 的話,就可以試試看目前有支援的轉換語法,像是頂層 await、類別的靜態初始化區塊等。
TypeScript
如果專案是以 TypeScript 開發,在目前的 beta 版可以透過 tsconfig.json
的 module
設定來支援頂層 await。
小結
這篇文章的內容,主要是擷取自我即將上市的書。如果有興趣的話,也歡迎在 11/12 後去天瓏翻翻看,或是在博客來等網站翻一下試閱頁。有對到你的電波的話,歡迎把它帶回家喔😆
這篇內容也有影片版可以觀看。在這裡也謝謝 JSDC 的邀請,讓我有了直播技術分享的初體驗。另外 JSDC 當天的議程內容真的很充實,受益良多。有時間的話,會再陸續整理相關心得。
參考連結
JSDC 2021 前導活動 | ECMAScript 關鍵 30 天 | Are you ready? ES2022!