大家好,我是若川。歡迎加我微信?ruochuan12,長期交流學習。今天分享一篇關于ES2021的5個新特性。點擊下方卡片關注我,或者查看源碼等系列文章。學習源碼整體架構系列、年度總結、JS基礎系列

在寫本文時,本文提到的新的 JavaScript 提案功能已進入第 4 階段,并且幾乎肯定會包含在 ES2021 中。你已經可以開始在 最新版本的瀏覽器,Node.js 和 Babel 中使用。
注意:ECMAScript 是 JavaScript 所基于的標準,由 TC39 委員會管理。ECMAScript 始終是一個不需要的名稱,這會使一切都對初學者感到困惑。人們經常談論 JavaScript 功能,但參考的是 ECMAScript 規范。
更新特性
數字分隔符(
_
)邏輯分配(
&&=
,||=
,??=
)引用不足(
WeakRef
和FinalizationRegistry
)Promise.any
String.prototype.replaceAll
1. 數值分隔符
大數字文字很難使人眼快速解析,尤其是當有很多重復的數字時:
1000000000000???1019436871.42
為了提高可讀性,新的 JavaScript 語言功能 啟用了下劃線作為數字文字中的分隔符。因此,上面的內容現在可以重寫為每千位數字,例如:
1_000_000_000_000????1_019_436_871.42
現在,更容易說出第一個數字是 1 萬億,而第二個數字大約是 10 億。
數字分隔符有助于提高各種數字文字的可讀性:
//?A?decimal?integer?literal?with?its?digits?grouped?per?thousand:
1_000_000_000_000
//?A?decimal?literal?with?its?digits?grouped?per?thousand:
1_000_000.220_720
//?A?binary?integer?literal?with?its?bits?grouped?per?octet:
0b01010110_00111000
//?A?binary?integer?literal?with?its?bits?grouped?per?nibble:
0b0101_0110_0011_1000
//?A?hexadecimal?integer?literal?with?its?digits?grouped?by?byte:
0x40_76_38_6A_73
//?A?BigInt?literal?with?its?digits?grouped?per?thousand:
4_642_473_943_484_686_707n
它們甚至適用于八進制整數文字(盡管 我想不出 其中分隔符為此類文字提供值 的示例):
//?A?numeric?separator?in?an?octal?integer?literal:??????♀?
0o123_456
請注意,JavaScript 還具有不帶顯式 0o
前綴的八進制文字的舊式語法。例如,017 === 0o17
。在嚴格模式下或模塊內不支持此語法,并且在現代代碼中不應使用此語法。因此,這些文字不支持數字分隔符。使用 0o17
風格的文字代替。
2. Promise combinators
自從 ES2015 中引入 Promise 以來,JavaScript 完全支持兩種 Promise 組合器:靜態方法 Promise.all 和 Promise.race。
目前有兩個新提案正在通過標準化流程:Promise.allSettled 和 Promise.any。有了這些添加,JavaScript 中將總共有四個諾言組合器,每個組合器支持不同的用例。
以下是這四個組合器的概述:

2.1 Promise.allSettled
Promise.allSettled 給你當所有輸入的諾言是一種信號結算,這意味著他們要么履行或拒絕。如果您不在乎承諾的狀態,而只是想知道工作何時完成,無論它是否成功,這都是很有用的。
例如,您可以啟動一系列獨立的 API 調用,并使用 Promise.allSettled 它們來確保它們已全部完成,然后再執行其他操作,例如刪除加載微調器:
const?promises?=?[fetch('/api-call-1'),fetch('/api-call-2'),fetch('/api-call-3'),
];
//?Imagine?some?of?these?requests?fail,?and?some?succeed.await?Promise.allSettled(promises);
//?All?API?calls?have?finished?(either?failed?or?succeeded).
removeLoadingIndicator();
2.2 Promise.any
Promise.any
方法和 Promise.race
類似——只要給定的迭代中的一個 promise
成功,就采用第一個 promise
的值作為它的返回值,但與 Promise.race
的不同之處在于——它會等到所有 promise
都失敗之后,才返回失敗的值:
const?promises?=?[fetch('/endpoint-a').then(()?=>?'a'),fetch('/endpoint-b').then(()?=>?'b'),fetch('/endpoint-c').then(()?=>?'c'),
];
try?{const?first?=?await?Promise.any(promises);//?Any?of?the?promises?was?fulfilled.console.log(first);//?→?e.g.?'b'
}?catch?(error)?{//?All?of?the?promises?were?rejected.console.assert(error?instanceof?AggregateError);//?Log?the?rejection?values:console.log(error.errors);//?→?[//?????<TypeError:?Failed?to?fetch?/endpoint-a>,//?????<TypeError:?Failed?to?fetch?/endpoint-b>,//?????<TypeError:?Failed?to?fetch?/endpoint-c>//???]
}
此代碼示例檢查哪個端點響應最快,然后將其記錄下來。只有當 所有 請求都失敗時,我們才最終進入代碼 catch
塊,然后在其中處理錯誤。
Promise.any
拒絕可以一次代表多個錯誤。為了在語言級別支持此功能,引入了一種新的錯誤類型,稱為 AggregateError
。除了上面示例中的基本用法外,還可以以編程方式構造 AggregateError
對象,就像其他錯誤類型一樣:
const?aggregateError?=?new?AggregateError([errorA,?errorB,?errorC],?'Stuff?went?wrong!');
3. Weak references and finalizers
此功能包含兩個高級對象 WeakRef
和 FinalizationRegistry
。根據使用情況,這些接口可以單獨使用,也可以一起使用。正確使用它們需要仔細考慮,如果可能,最好避免使用它們。
一般來說,在JavaScript中,對象的引用是強保留的,這意味著只要持有對象的引用,它就不會被垃圾回收。
const?ref?=?{?x:?42,?y:?51?};
//?只要我們訪問?ref?對象(或者任何其他引用指向該對象),這個對象就不會被垃圾回收
目前在 Javascript 中,WeakMap 和 WeakSet 是弱引用對象的唯一方法:將對象作為鍵添加到 WeakMap 或 WeakSet 中,是不會阻止它被垃圾回收的。
JavaScript 的 WeakMap 并不是真正意義上的弱引用:實際上,只要鍵仍然存活,它就強引用其內容。WeakMap 僅在鍵被垃圾回收之后,才弱引用它的內容。
WeakRef 是一個更高級的 API,它提供了真正的弱引用,Weakref 實例具有一個方法 deref,該方法返回被引用的原始對象,如果原始對象已被收集,則返回 undefined 對象。
JavaScript 中對象的引用是強引用,WeakMap 和 WeakSet 可以提供部分的弱引用功能,若想在 JavaScript 中實現真正的弱引用,可以通過配合使用 WeakRef 和終結器(Finalizer)來實現。
WeakRef 是用來指目標對象不脫離垃圾收集保留它的對象。如果未通過垃圾回收回收目標對象,則 WeakRefs 可以取消引用以允許訪問目標對象。
//?Create?a?WeakRef?object?referring?to?a?given?target?object
const?ref?=?new?WeakRef(targetObject)//?Return?the?WeakRef?instance's?target?object,?or?undefined?if?the?target?object?has?been?garbage-collected
const?obj?=?ref.deref()
使用 FinalizationRegistry 對象可以在垃圾回收對象時請求回調。
//?Create?a?registry?object?that?uses?the?given?callback
const?registry?=?new?FinalizationRegistry([callback])//?Register?an?object?with?a?registry?instance?so?that?if?the?object?is?garbage-collected,?the?registry's?callback?may?get?called
registry.register(target,?heldValue,?[unregisterToken])//?Unregister?a?target?object?from?a?registry?instance
registry.unregister(unregisterToken)
更多信息:TC39提案,V8
4. String.prototype.replaceAll
當前,如果不使用全局正則表達式,就無法替換字符串中子字符串的所有實例。與字符串參數一起使用時,String.prototype.replace 僅影響首次出現。
String.prototype.replaceAll()
?將為開發人員提供一種簡單的方法來完成此常見的基本操作。
'aabbcc'.replaceAll('b',?'.')?//?'aa..cc'
'aabbcc'.replaceAll(/b/g,?'.')?//?'aa..cc'
5. Logical assignment (邏輯分配)
支持與新的運營邏輯分配 &&=
,||=
和 ??=
。與它們的 數學和按位對應物不同,邏輯分配遵循其各自邏輯操作的短路行為。僅當邏輯運算將評估右側時,它們才執行分配。
//?falsy:?false,?0,?-0,?0n,?"",?null,?undefined,?and?NaN
//?truthy:?all?values?are?truthy?unless?defined?as?falsy
//?nullish:?null?or?undefineda?||=?b
//?Logical?OR?assignment
//?Equivalent?to:?a?||?(a?=?b);
//?Only?assigns?if?a?is?falsya?&&=?b
//?Logical?AND?assignment
//?Equivalent?to:?a?&&?(a?=?b);
//?Only?assigns?if?a?is?truthya???=?b
//?Logical?nullish?assignment
//?Equivalent?to:?a????(a?=?b);
//?Only?assigns?if?a?is?nullish
5.1 具體例子
帶有 &&
運算符的邏輯賦值運算符
僅當 LHS 值為真時,才將 RHS 變量值賦給 LHS 變量。
//?Logical?Assignment?Operator?with?&&?operator
let?num1?=?5
let?num2?=?10
num1?&&=?num2
console.log(num1)?//?10
//?Line?5?can?also?be?written?as?following?ways
//?1.?num1?&&?(num1?=?num2)
//?2.?if?(num1)?num1?=?num2
帶有 ||
的運算符邏輯賦值運算符
僅當 LHS 值為假時,才將 RHS 變量值賦給 LHS 變量。
//?Logical?Assignment?Operator?with?||?operator
let?num1
let?num2?=?10
num1?||=?num2
console.log(num1)?//?10
//?Line?5?can?also?be?written?as?following?ways
//?1.?num1?||?(num1?=?num2)
//?2.?if?(!num1)?num1?=?num2
帶有 ??
運算符的邏輯賦值運算符
ES2020 引入了空值合并運算符,其也可以與賦值運算符結合使用。僅當 LHS 為 undefined 或僅為 null 時,才將 RHS 變量值賦給 LHS 變量。
//?Logical?Assignment?Operator?with????operator
let?num1
let?num2?=?10
num1???=?num2
console.log(num1)?//?10
num1?=?false
num1???=?num2
console.log(num1)?//?false
//?Line?5?can?also?be?written?as?following?ways
//?num1????(num1?=?num2)
概括

作為開發人員,跟緊語言的新特性是很重要的。
以上將在 2021 年發布的一些新功能,它們是進入第 4 階段的提案,幾乎可以肯定會包括在內,這些功能已經在最新的瀏覽器和 babel 中實現。
參考文章:JavaScript Features in 2021
最近組建了一個江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你進群。
·················?若川出品?·················
今日話題
今天分享一個chrome瀏覽器標簽預覽功能,打開chrome://flags,搜索tab hover Card Images,改成Enabled就開啟啦,快試試吧。歡迎分享、收藏、點贊、在看我的公眾號文章~
一個愿景是幫助5年內前端人走向前列的公眾號
可加我個人微信 ruochuan12,長期交流學習
推薦閱讀
我在阿里招前端,我該怎么幫你?(現在還能加我進模擬面試群)
如何拿下阿里巴巴 P6 的前端 Offer