新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)“前端先鋒”(jingchengyideng)。

簡(jiǎn)述
ES2021(ES12)將于 2021 年中發(fā)布。在本文中,你將將會(huì)了解五個(gè)最有趣的功能:String.prototype.replaceAll(),數(shù)字分隔符,邏輯賦值運(yùn)算符,Promise.any(),WeakRef 和Finalizers。
本文所描述的五個(gè)功能目前都處于第 4 階段。這意味著它們已經(jīng)完成,并將要在 JavaScript 引擎中實(shí)現(xiàn)了。這意味著你不會(huì)浪費(fèi)時(shí)間去學(xué)習(xí)一些可能永遠(yuǎn)也不會(huì)出現(xiàn)的東西。
這些功能不久將會(huì)發(fā)布。如果有興趣,可以到官方 Ecma TC39 GitHub (https://github.com/tc39/proposals) 去了解有關(guān)其他提案的更多信息。這個(gè) Github 庫(kù)跟蹤了所有提案以及其當(dāng)前所處的階段。
String.prototype.replaceAll()
先從一個(gè)小功能 replaceAll() 開(kāi)始,這是對(duì) JavaScript 語(yǔ)言的一個(gè)補(bǔ)充。當(dāng)你要替換字符串中多次出現(xiàn)的匹配模式時(shí),目前可以用 replace() 方法,但問(wèn)題是它只能替換第一次出現(xiàn)的那個(gè)。
這并不意味著 replace() 不能替換所有出現(xiàn)的匹配模式,只不過(guò)你必須用正則表達(dá)式才行。如果你可以接受那就沒(méi)事兒了。不過(guò)對(duì)于很多 js 程序員來(lái)說(shuō),正則表達(dá)式并不是他們的菜(實(shí)際上是懶得學(xué)!)。
如果你就是這樣的 js 程序員,肯定喜歡新的 replaceAll() 方法。它的工作方式與 replace() 類似,區(qū)別在于 replaceAll() 可以不用正則表達(dá)式就能替換所有出現(xiàn)的模式。
replaceAll() 也能接受正則表達(dá)式,你完全可以用它代替 replace() 。
- // 聲明一個(gè)字符串
- let str = 'There are those who like cats, there those who like watching cats and there are those who have cats.'
- // 用 dogs 替換所有的“cats”:
- strstr = str.replaceAll('cats', 'dogs')
- console.log(str)
- // Output:
- // 'There are those who like dogs, there those who like watching dogs and there are those who have dogs.'
- // 用 replace() 的寫(xiě)法:
- strstr = str.replace(/cats/g, 'dogs')
- console.log(str)
- // Output:
- // 'There are those who like dogs, there those who like watching dogs and there are those have dogs.'
數(shù)字分隔符
這是 JavaScript ES2021的一個(gè)非常小的功能,可以讓你在處理大量數(shù)字時(shí)更好過(guò)一點(diǎn)。數(shù)字分隔符提供了一種能使大數(shù)字更易于閱讀和使用的簡(jiǎn)單方法。語(yǔ)法也很簡(jiǎn)單:一個(gè)下劃線 _。
- // 不帶數(shù)字分隔符的 Number
- const num = 3685134689
- // 帶數(shù)字分隔符的 Number
- const num = 3_685_134_689
不過(guò)數(shù)字分隔符只是在視覺(jué)上提供一些幫助。在使用時(shí)不會(huì)對(duì)數(shù)值本身產(chǎn)生任何影響。
- // 帶數(shù)字分隔符的 Number
- const num = 3_685_134_689
- // 輸出:
- console.log(num)
- // Output:
- // 3685134689
邏輯賦值運(yùn)算符
JavaScript 允許在布爾上下文中使用邏輯運(yùn)算符。例如在 if ... else語(yǔ)句和三目運(yùn)算符中檢測(cè)是 true 還是 false。ES2021 的邏輯賦值運(yùn)算符將邏輯運(yùn)算符與賦值表達(dá)式(=)組合在了一起。
在 JavaScript 中已經(jīng)有了一些賦值運(yùn)算符,例如:加法賦值(+=),減法賦值(-=),乘法賦值(*=)等。在 ES2021 中又增加了對(duì)邏輯運(yùn)算符 &&,|| 和 ??([空值合并)的支持。
- //////////////////
- // 邏輯與賦值運(yùn)算符 (&&=)
- //////////////////
- x &&= y
- // 以上代碼相當(dāng)于:
- xx = x && d
- // 或者:
- if (x) {
- x = y
- }
- // 例1:
- let x = 3
- let y = 0
- x &&= y
- console.log(x)
- // Output:
- // 0
- // 例 2:
- let x = 0
- let y = 9
- x &&= y
- console.log(x)
- // Output:
- // 0
- // 例 3:
- let x = 3 // Truthy value.
- let y = 15 // Truthy value.
- x &&= y
- console.log(x)
- // Output:
- // 15
- //////////////////
- // 邏輯或賦值運(yùn)算符 (||=):
- x ||= y
- // 相當(dāng)于:
- xx = x || y
- // 或者:
- if (!x) {
- x = y
- }
- // 例 1:
- let x = 3
- let y = 0
- x ||= y
- console.log(x)
- // Output:
- // 3
- // 例 2:
- let x = 0
- let y = 9
- x ||= y
- console.log(x)
- // Output:
- // 9
- // 例 3:
- let x = 3
- let y = 15
- x ||= y
- console.log(x)
- // Output:
- // 3
- /////////////////////////
- // 空值合并賦值運(yùn)算符 (??=):
- /////////////////////////
- x ??= y
- // 相當(dāng)于:
- xx = x ?? y
- // 或者:
- if (x == null || x == undefined) {
- x = y
- }
- // 例 1:
- let x = null
- let y = 'Hello'
- x ??= y
- console.log(x)
- // Output:
- // 'Hello'
- // 例 2:
- let x = 'Jay'
- let y = 'Hello'
- x ??= y
- console.log(x)
- // Output:
- // 'Jay'
- // 例 3:
- let x = 'Jay'
- let y = null
- x ??= y
- console.log(x)
- // Output:
- // 'Jay'
- // 例 4:
- let x = undefined
- let y = 'Jock'
- x ??= y
- console.log(x)
- // Output:
- // 'Jock'
看一下上面的例子。首先是 x && = y。僅當(dāng) x 為真時(shí),才將 y 賦值給 x。其次是 x || = y,僅當(dāng) x 為假時(shí),才將 y 賦值給 x。如果 x 是真,而 y 是假,則不會(huì)進(jìn)行賦值。
如果 x 和 y 都是假,也會(huì)發(fā)生同樣的情況。最后是 x ?? = y。僅當(dāng) x 為 null 或 undefined 時(shí),才將 y 分配給 x。如果 x 既不是 null 也不是 undefined 則不會(huì)進(jìn)行賦值,如果 y 為 null 或 undefined 也一樣。
Promise.any()
在 ES6 中引入了 Promise.race() 和 Promise.all() 方法,ES2020 加入了 Promise.allSettled()。ES2021 又增加了一個(gè)使 Promise 處理更加容易的方法:Promise.any() 。
Promise.any() 方法接受多個(gè) promise,并在完成其中任何一個(gè)的情況下返回 promise。其返回的是 Promise.any() 完成的第一個(gè) promise。如果所有 promise 均被拒絕,則 Promise.any() 將返回 AggregateError,其中包含拒絕的原因。
- // 例 1: 全部被完成:
- // 創(chuàng)建 promises:
- const promise1 = new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve('promise1 is resolved.')
- }, Math.floor(Math.random() * 1000))
- })
- const promise2 = new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve('promise2 is resolved.')
- }, Math.floor(Math.random() * 1000))
- })
- const promise3 = new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve('promise3 is resolved.')
- }, Math.floor(Math.random() * 1000))
- })
- ;(async function() {
- // Await the result of Promise.any():
- const result = await Promise.any([promise1, promise2, promise3])
- console.log(result)
- // Output:
- // 'promise1 is resolved.', 'promise2 is resolved.' or 'promise3 is resolved.'
- })()
- // 例 2: 部分完成:
- const promise1 = new Promise((resolve, reject) => {
- setTimeout(() => {
- resolve('promise1 is resolved.')
- }, Math.floor(Math.random() * 1000))
- })
- const promise2 = new Promise((resolve, reject) => {
- setTimeout(() => {
- reject('promise2 was rejected.')
- }, Math.floor(Math.random() * 1000))
- })
- ;(async function() {
- // Await the result of Promise.any():
- const result = await Promise.any([promise1, promise2])
- console.log(result)
- // Output:
- // 'promise1 is resolved.'
- })()
- // 例 3: 均被拒絕:
- const promise1 = new Promise((resolve, reject) => {
- setTimeout(() => {
- reject('promise1 was rejected.')
- }, Math.floor(Math.random() * 1000))
- })
- const promise2 = new Promise((resolve, reject) => {
- setTimeout(() => {
- reject('promise2 was rejected.')
- }, Math.floor(Math.random() * 1000))
- })
- ;(async function() {
- // Use try...catch to catch the AggregateError:
- try {
- // Await the result of Promise.any():
- const result = await Promise.any([promise1, promise2])
- }
- catch (err) {
- console.log(err.errors)
- // Output:
- // [ 'promise1 was rejected.', 'promise2 was rejected.' ]
- }
- })()
弱引用:WeakRef
最后一個(gè)搶眼的功能是 WeakRefs。在 JavaScript 中,當(dāng)你創(chuàng)建了一個(gè)創(chuàng)建對(duì)象的引用時(shí),這個(gè)引用可以防止對(duì)象被 gc 回收,也就是說(shuō) JavaScript 無(wú)法刪除對(duì)象并釋放其內(nèi)存。只要對(duì)該對(duì)象的引用一直存在,就可以使這個(gè)對(duì)象永遠(yuǎn)存在。
ES2021 了新的類 WeakRefs。允許創(chuàng)建對(duì)象的弱引用。這樣就能夠在跟蹤現(xiàn)有對(duì)象時(shí)不會(huì)阻止對(duì)其進(jìn)行垃圾回收。對(duì)于緩存和對(duì)象映射非常有用。
必須用 new關(guān)鍵字創(chuàng)建新的 WeakRef ,并把某些對(duì)象作為參數(shù)放入括號(hào)中。當(dāng)你想讀取引用(被引用的對(duì)象)時(shí),可以通過(guò)在弱引用上調(diào)用 deref() 來(lái)實(shí)現(xiàn)。下面是一個(gè)非常簡(jiǎn)單的例子。
- const myWeakRef = new WeakRef({
- name: 'Cache',
- size: 'unlimited'
- })
- console.log(myWeakRef.deref())
- // Output:
- // { name: 'Cache', size: 'unlimited' }
- console.log(myWeakRef.deref().name)
- // Output:
- // 'Cache'
- console.log(myWeakRef.deref().size)
- // Output:
- // 'unlimited'
Finalizers 和 FinalizationRegistry
與 WeakRef 緊密相連的還有另一個(gè)功能,名為 finalizers 或 FinalizationRegistry。這個(gè)功能允許你注冊(cè)一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)將會(huì)在對(duì)象被 gc 回收時(shí)調(diào)用。
- // 創(chuàng)建 FinalizationRegistry:
- const reg = new FinalizationRegistry((val) => {
- console.log(val)
- })
- ;(() => {
- // 創(chuàng)建新對(duì)象:
- const obj = {}
- //為 “obj” 對(duì)象注冊(cè) finalizer:
- //第一個(gè)參數(shù):要為其注冊(cè) finalizer 的對(duì)象。
- //第二個(gè)參數(shù):上面定義的回調(diào)函數(shù)的值。
- reg.register(obj, 'obj has been garbage-collected.')
- })()
- // 當(dāng) "obj" 被gc回收時(shí)輸出:
- // 'obj has been garbage-collected.'
官方建議不要輕易使用 WeakRef 和 finalizer。其中一個(gè)原因是它們可能不可預(yù)測(cè),另一個(gè)是它們并沒(méi)有真正幫 gc 完成工作,實(shí)際上可能會(huì)gc的工作更加困難。你可以在它的提案(https://github.com/tc39/proposal-weakrefs#a-note-of-caution)中詳細(xì)了解其原因。
總結(jié)
與以前的 JavaScript 規(guī)范(例如 ES6 和 ES2020)相比,看上去 ES2021的更新不多,但是這些有趣的功能值得我們關(guān)注。
當(dāng)前名稱:即將發(fā)布的ES2021中有哪些有趣的功能
網(wǎng)頁(yè)地址:http://www.5511xx.com/article/ccigdcd.html


咨詢
建站咨詢
