種草 ECMAScript 2021 新特性
「觀感度:??????????」
「口味:賽螃蟹」
「烹飪時間:5min」
ECMAScript
ECMAScript 是 Ecma International 頒布的一部語言標(biāo)準(zhǔn),編號為 262,又稱為 ECMA-262。
Ecma International 則是一個制定信息和通訊技術(shù)方面的國際標(biāo)準(zhǔn)的組織,前身是歐洲計算機(jī)制造商協(xié)會(European Computer Manufacturers Association),隨著計算機(jī)的國際化,機(jī)構(gòu)名稱改為其英文單詞首字母縮寫。
ECMAScript 由 EMCA International 的 TC39(Technical Committee 39)技術(shù)委員會編寫。
TC39 會將編寫完成的 ECMAScript 標(biāo)準(zhǔn)文檔提交給 Ecma International,并由其正式發(fā)布。
從 2015 年開始,ECMAScript 每年都會發(fā)布一個正式版,并在標(biāo)題中寫上年份,比如「ECMAScript? 2020 Language Specification, 11th edition」,可簡稱為ES2020或ES11。
五個流程階段
如果想要新增或是改寫規(guī)范,一般要經(jīng)歷5個階段,如 TC39 Process 中所示:
Strawperson Proposal Draft Candidate Finished
經(jīng)歷過這5個階段,進(jìn)入 Finished 狀態(tài)的修改才會被列入正式版的規(guī)范。
ECMAScript2021
https://github.com/tc39/proposals/blob/master/finished-proposals.md
了解了 ECMAScript,下面就進(jìn)入正文,讓我們來看看已經(jīng)確定的 ECMAScript2021 的新特性吧。
1.String.prototype.replaceAll
https://github.com/tc39/proposal-string-replaceall
先來回顧下 String.prototype.replace 的用法:
const?str?=?'Stay?Hungry.?Stay?Foolish.'
const?newStr?=?str.replace('Stay',?'Always')
console.log(newStr)?//?Always?Hungry.?Stay?Foolish.
如果我們這樣寫,只有第一個匹配的會被替換。
想要做到全部替換就需要使用正則表達(dá)式。
const?str?=?'Stay?Hungry.?Stay?Foolish.'
const?newStr?=?str.replace(/Stay/g,?'Always')
console.log(newStr)?//?Always?Hungry.?Always?Foolish.
不過在使用正則的時候,如果需求是匹配 + 等符號時,還需要進(jìn)行轉(zhuǎn)義。如:
/\+/g
聰明的你也許會想到另外一種方案:使用 split + join 的方式
這里借用下官方的例子:
const?queryString?=?'q=query+string+parameters';
const?withSpaces?=?queryString.split('+').join('?');
//?q=query?string?parameters
但這樣做也是有性能開銷的,加上這種操作十分常見。于是就誕生了 String.prototype.replaceAll 這個 API,我們可以更加方便的來進(jìn)行操作。
const?str?=?'Stay?Hungry.?Stay?Foolish.'
const?newStr?=?str.replaceAll('Stay',?'Always')
console.log(newStr)?//?Always?Hungry.?Always?Foolish.
String.prototype.replaceAll(searchValue,?replaceValue)
注意:當(dāng) searchValue 是非全局正則表達(dá)式時,replaceAll 會引發(fā)異常。如果 searchValue 是全局正則表達(dá)式時,replaceAll 與 replace 行為是一致的。
2.Promise.any
https://github.com/tc39/proposal-promise-any
const?p?=?Promise.all([p1,?p2,?p3]);
Promise.all(ES2015) 只有當(dāng)傳入的每個 Promise 實例(p1,p2,p3)的狀態(tài)都變成 fulfilled 時,p 才 fulfilled,只要(p1,p2,p3)有一個被 rejected,p 的狀態(tài)就變成 rejected。Promise.race(ES2015) ?當(dāng)傳入的 Promise 實例(p1,p2,p3)中有一個率先改變狀態(tài),那么 p 的狀態(tài)就跟著改變,也就是說返回最先改變的 Promise 實例的返回值。Promise.allSettled(ES2020) 只有等到所有傳入的 Promise 實例(p1,p2,p3)都返回結(jié)果,不管是 fulfilled 還是 rejected,包裝實例才會結(jié)束。Promise.any(ES2021) 當(dāng)其中任何一個 Promise 完成(fulfilled)時,就返回那個已經(jīng)有完成值的 Promise。如果所有的 Promise 都拒絕 (rejected), 那么返回一個拒絕的 Promise。
對比記憶
我們可以把 Promise.any()理解成Promise.all()的反向操作。

「致敬韋神!」
Promise.any()跟Promise.race()方法很像,有一個不同點(diǎn)是:前者不會因為某個Promise變成rejected狀態(tài)而結(jié)束。
想要了解更多細(xì)節(jié)可以看阮老師的ECMAScript 6 入門
Promise.any(promises).then(
????(first)?=>?{
????????//?任何一個Promise完成
????},
????(error)?=>?{
????????//?所有的?Promise都拒絕了
????}
)
any 名字的由來
any 顧名思義,不僅清楚的描述了它的作用,而且在提供此功能的第三方庫中都是這樣命名的,用過的同學(xué)們一定覺得很親切。
https://github.com/kriskowal/q#combination http://bluebirdjs.com/docs/api/promise.any.html https://github.com/m0ppers/promise-any https://github.com/cujojs/when/blob/master/docs/api.md#whenany https://github.com/sindresorhus/p-any
可預(yù)見的作用
官方提供了一個例子,可以應(yīng)用 Promise.any() 檢查哪個站點(diǎn)訪問最快。
Promise.any([
??fetch('https://v8.dev/').then(()?=>?'home'),
??fetch('https://v8.dev/blog').then(()?=>?'blog'),
??fetch('https://v8.dev/docs').then(()?=>?'docs')
]).then((first)?=>?{
??//?Any?of?the?promises?was?fulfilled.
??console.log(first);
??//?→?'home'
}).catch((error)?=>?{
??//?All?of?the?promises?were?rejected.
??console.log(error);
});
3.WeakRefs
https://github.com/tc39/proposal-weakrefs
注意:要盡量避免使用 WeakRef 和 FinalizationRegistry,垃圾回收機(jī)制依賴于 JavaScript 引擎的實現(xiàn),不同的引擎或是不同版本的引擎可能會有所不同。
這個提案主要包括兩個主要的新功能:
使用 WeakRef類創(chuàng)建對象的弱引用使用 FinalizationRegistry類對對象進(jìn)行垃圾回收后,運(yùn)行用戶定義的終結(jié)器
它們可以分開使用也可以一起使用。
WeakRef 實例不會阻止 GC 回收,但是 GC 會在兩次 EventLoop 之間回收 WeakRef 實例。GC 回收后的 WeakRef 實例的 deref() 方法將會返回undefined。
let?ref?=?new?WeakRef(obj)
let?isLive?=?ref.deref()?//?如果?obj?被垃圾回收了,那么?isLive?就是?undefined
FinalizationRegistry 注冊 Callback,某個對象被 GC 回收后調(diào)用。
const?registry?=?new?FinalizationRegistry(heldValue?=>?{
??//?....
});
//?通過?register?注冊任何你想要清理回調(diào)的對象,傳入該對象和所含的值
registry.register(theObject,?"some?value");
關(guān)于更多的細(xì)節(jié)你可以查閱:
https://github.com/tc39/proposal-weakrefs/blob/master/reference.md
4.Logical Assignment Operators 邏輯賦值操作符
https://github.com/tc39/proposal-logical-assignment
先來回顧下 ES2020 新增的空值合并操作符 ??
在當(dāng)左側(cè)操作數(shù)為 undefined 或 null 時,該操作符會將右側(cè)操作數(shù)賦值給左側(cè)變量。
const?name?=?null????'前端食堂'
console.log(name)?//?前端食堂
有了邏輯賦值運(yùn)算符,我們可以替換掉如下舊的寫法:
const?demo?=?function()?{
????//?舊的寫法1
????//?if?(!a)?{
????//?????a?=?'西瓜'
????//?}
????//?舊的寫法2
????//?a?=?a?||?'西瓜'
????//?新的寫法
????a?||=?'西瓜'?
}
a?||=?b;?//?等同于?a?||?(a?=?b);
a?&&=?b;?//?等同于?a?&&?(a?=?b);
a???=?b;?//?等同于?a????(a?=?b);
5.Numeric separators 數(shù)字分隔符
https://github.com/tc39/proposal-numeric-separator
數(shù)字的可讀性隨著數(shù)字變長而變差,數(shù)字分隔符會讓長數(shù)字更加清晰易讀。
const?x?=?1000000000000
const?y?=?1_000_000_000_000
console.log(x?===?y)?//?true
在二進(jìn)制、十六進(jìn)制、BigInt 等中都可以使用。
推薦閱讀
