“學不動了!”系列之 ES2021 搶先嚐

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從 ES2015(ES6)之後,每年,JS 都會在其新標準裏添加一些有意思的新特性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們可以看一下已經進入 Stage 4 階段的提案,這些提案到時候都會進入 ES2021 的標準。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(Stage 4 是啥?)TC39 在把提案轉換爲最後的標準之前,這些提案都會經歷 State 1~4 四個階段。只有到 Stage 4 的提案會被標記爲“已完成”,並在將來進入到下一個 ES 標準裏。有興趣的話,可以點擊這裏查看目前每個 Stage 都有哪些提案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"特性一覽"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"String.prototype.replaceAll"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大家應該都使用過 "},{"type":"codeinline","content":[{"type":"text","text":"String.prototype.replace"}]},{"type":"text","text":" 來替換字符串中的某些匹配給定正則表達式的部分。但是,如果我們所使用的匹配規則不是一個正則表達式,而是一個普通的字符串,只有 "},{"type":"text","marks":[{"type":"strong"}],"text":"第一個"},{"type":"text","text":" 匹配的纔會被替換。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const str = 'I like frontend. I like JavaScript.';\nconst newStr = str.replace('like', 'love');\nnewStr;\n\/\/ \"I love frontend. I like JavaScript.\"\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你需要替換所有的 "},{"type":"codeinline","content":[{"type":"text","text":"\"like\""}]},{"type":"text","text":",那我們只能用正則表達式 "},{"type":"codeinline","content":[{"type":"text","text":"\/like\/g"}]},{"type":"text","text":" 來進行匹配。有"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"了 "},{"type":"codeinline","content":[{"type":"text","text":"String.prototype.replaceAll"}]},{"type":"text","text":" 這個 API,我們就可以輕鬆替換掉所有的字符串啦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const str = 'I like frontend. I like JavaScript.';\nconst newStr = str.replaceAll('like', 'love');\nnewStr;\n\/\/ \"I love frontend. I love JavaScript.\"\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實這個 API 在一些瀏覽器的最新版本已經得到了實現,只是還未進入標準。比如在 Edge、Opera 或者 Node.js 中我們就暫時無法使用這個 API。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"Promise.any"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":" 在過去的幾年裏,已經更新過了若干的新的 API。除了 ES6 的 "},{"type":"codeinline","content":[{"type":"text","text":"Promise.all"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"Promise.race"}]},{"type":"text","text":" 之外,還有去年發佈的 ES2020 中的 "},{"type":"codeinline","content":[{"type":"text","text":"Promise.allSettled"}]},{"type":"text","text":"。現在,我們來看一個新的 API:"},{"type":"codeinline","content":[{"type":"text","text":"Promise.any"}]},{"type":"text","text":"。從字面意思來看,相信聰明的你應該能大致猜出這個 API 的作用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"與 "},{"type":"codeinline","content":[{"type":"text","text":"Promise.all"}]},{"type":"text","text":" 類似,"},{"type":"codeinline","content":[{"type":"text","text":"Promise.any"}]},{"type":"text","text":" 也接受一個 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":" 的數組。當其中任何一個 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":" 完成(fullfill)時,就返回那個已經有完成值的 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":"。如果所有的 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":" 都拒絕(reject),則返回一個拒絕的 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":",該 "},{"type":"codeinline","content":[{"type":"text","text":"Promise"}]},{"type":"text","text":" 的返回值是一個 "},{"type":"codeinline","content":[{"type":"text","text":"AggregateError"}]},{"type":"text","text":" 對象。我們可以把 "},{"type":"codeinline","content":[{"type":"text","text":"Promise.any"}]},{"type":"text","text":" 理解成 "},{"type":"codeinline","content":[{"type":"text","text":"Promise.all"}]},{"type":"text","text":" 的相反操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"Promise.any(promises).then(\n  (first) => {\n    \/\/ 任何一個 Promise 完成了\n  },\n  (error) => {\n    \/\/ 所有的 Promise 都拒絕了\n  }\n);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"邏輯賦值操作符"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們知道,下面的代碼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let a = 0;\na = a + 2;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以簡寫爲:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let a = 0;\na += 2;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那麼這個新的標準中,邏輯表達式的操作符("},{"type":"codeinline","content":[{"type":"text","text":"&&"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"||"}]},{"type":"text","text":"、"},{"type":"codeinline","content":[{"type":"text","text":"??"}]},{"type":"text","text":")也可以簡寫啦。(關於 ES2020 標準的 "},{"type":"codeinline","content":[{"type":"text","text":"??"}]},{"type":"text","text":" 操作符,後文會稍微補充一下)。我們看一下示例代碼:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/\/ 等同於 a = a || b\na ||= b;\n\/\/ 等同於 c = c && d\nc &&= d;\n\/\/ 等同於 e = e ?? f\n\/\/ 咦,?? 這是啥\ne ??= f;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這裏,補充一下去年發佈的標準中的新的邏輯操作符 "},{"type":"codeinline","content":[{"type":"text","text":"??"}]},{"type":"text","text":" 的用法。大家可能遇到過,如果一個變量是空,需要給它賦值爲一個默認值的情況。新手同學可能會這麼寫:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let count = realCount || '無法獲取'"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,以上的代碼會有一個 bug。如果 "},{"type":"codeinline","content":[{"type":"text","text":"realCount"}]},{"type":"text","text":" 的值是 "},{"type":"codeinline","content":[{"type":"text","text":"0"}]},{"type":"text","text":",則會被當作取不到其值,會取到 "},{"type":"codeinline","content":[{"type":"text","text":"'無法獲取'"}]},{"type":"text","text":" 這個字符串。而如果我們使用了 "},{"type":"codeinline","content":[{"type":"text","text":"??"}]},{"type":"text","text":",只有當操作符左邊的值是 "},{"type":"codeinline","content":[{"type":"text","text":"null"}]},{"type":"text","text":" 或者 "},{"type":"codeinline","content":[{"type":"text","text":"undefined"}]},{"type":"text","text":" 的時候,纔會取操作符右邊的值:"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"let count = realCount ?? '無法獲取'\n"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"數字分隔符"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你要寫一個很長的數字的時候:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let x = 233333333"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數字太長會導致可讀性很差。使用了數字分隔符 "},{"type":"codeinline","content":[{"type":"text","text":"_"}]},{"type":"text","text":" (下劃線),就可以讓數字讀的更清晰:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let x = 2_3333_3333\n\/\/ x 的值等同於 233333333,只是這樣可讀性更強,不用一位一位數了"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"WeakRef"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"WeakRef"}]},{"type":"text","text":" 是一個 Class,一個 "},{"type":"codeinline","content":[{"type":"text","text":"WeakRef"}]},{"type":"text","text":" 對象可以讓你拿到一個對象的弱引用。這樣,就可以不用阻止垃圾回收這個對象了。我們可以使用其構造函數來創建一個 "},{"type":"codeinline","content":[{"type":"text","text":"WeakRef"}]},{"type":"text","text":" 對象"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/\/ someObj 不會因爲 ref 引用了這個對象,而不會被垃圾回收\nlet ref = new WeakRef(someObj);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那我們在使用上述代碼中的 "},{"type":"codeinline","content":[{"type":"text","text":"someObj"}]},{"type":"text","text":" 對象時,就可以用 "},{"type":"codeinline","content":[{"type":"text","text":"WeakRef.prototype.deref()"}]},{"type":"text","text":" 來取道。但是,在被引用對象被垃圾回收之後,這個函數就會返回 "},{"type":"codeinline","content":[{"type":"text","text":"undefined"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"\/\/ 如果 someObj 被垃圾回收了,則 obj 就會是 undefined\nlet obj = ref.deref();"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"Intl.ListFormat"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Intl.ListFormat"}]},{"type":"text","text":" 是一個構造函數,用來處理和多語言相關的對象格式化操作。來通過一個例子瞭解一下。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"const list = ['Apple', 'Orange', 'Banana']\nnew Intl.ListFormat('en-GB', { style: 'long', type: 'conjunction' }).format(list);\n\/\/ \"Apple, Orange and Banana\"\nnew Intl.ListFormat('zh-cn', { style: 'short', type: 'conjunction' }).format(list);\n\/\/ 會根據語言來返回相應的格式化操作\n\/\/ \"Apple、Orange和Banana\""}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個 API 支持多國語言,具體的 API 可以參考 這裏。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"Intl.DateTimeFormat"}]},{"type":"text","text":" API 中的 "},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"date"}]},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"Style"}]},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong"}],"text":"timeStyle"}]},{"type":"text","text":" 的配置項"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Intl.DateTimeFormat"}]},{"type":"text","text":" 是一個用來處理多語言下的時間日期格式化的函數。ES2021 中給這個函數添加了兩個新的參數:"},{"type":"codeinline","content":[{"type":"text","text":"dateStyle"}]},{"type":"text","text":" 和 "},{"type":"codeinline","content":[{"type":"text","text":"timeStyle"}]},{"type":"text","text":"。下面我們來通過例子來看一下這兩個參數的用法:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let o = new Intl.DateTimeFormat(\"en\" , {\n  timeStyle: \"short\"\n});\nconsole.log(o.format(Date.now())); \/\/ \"13:31\"\nlet o = new Intl.DateTimeFormat(\"en\" , {\n  dateStyle: \"short\"\n});\nconsole.log(o.format(Date.now())); \/\/ \"21.03.2012\"\n\/\/ 可以通過同時傳入 timeStyle 和 dateStyle 這兩個參數來獲取更完整的格式化時間的字符串\nlet o = new Intl.DateTimeFormat(\"en\" , {\n  timeStyle: \"medium\",\n  dateStyle: \"short\"\n});\nconsole.log(o.format(Date.now())); \/\/ \"21.03.2012, 13:31\"\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讀完是不是心動了?這些 API 在最新版的 Chrome 都已經得到了支持,趕緊嚐嚐鮮吧。如果要在生產環境中使用,記得處理兼容性問題哦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頭圖:Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者:陳宇清"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:https:\/\/mp.weixin.qq.com\/s\/O78fK2Yh_XQE1y23QSQxRg"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文:“學不動了!”系列之 ES2021 搶先嚐"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來源:微醫大前端技術 - 微信公衆號 [ID:wed_fed]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉載:著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章