
英文 | https://www.infoworld.com/article/3658393/8-great-new-javascript-language-features-in-es12.html
翻譯 | 楊小愛
JavaScript 語言規範,也稱為 ECMAScript 或 ES,是一個動态文檔,每年都會根據不斷變化的需求進行修改。雖然 JavaScript 最初是一種腳本語言,但 ECMAScript 規範概述指出,該語言“現在被用于許多不同環境和規模的全方位程式設計任務。”是以,JavaScript 被更好地了解為一種功能齊全的通用用途的程式設計語言。
随着即将釋出的 ECMAScript 2022 版本即将釋出,讓我們來看看 ECMAScript 2021 中引入的新 JavaScript 語言功能。
String.prototype.replaceAll
replaceAll() 方法将一個字元串或正規表達式(稱為模式)作為其第一個參數。第二個參數是模式的替換。給定第一個和第二個參數,replaceAll() 傳回一個新字元串,它将作為源字元串,其中模式的所有執行個體都被替換為替換。源字元串不受影響。
在 ECMAScript 2021 中,replaceAll() 與 ECMAScript 2020 的 matchAll() 一起改進了 JavaScript 内置 String 對象的固有功能。
replaceAll() 方法的工作方式與 replace() 完全相同,但适用于字元串中的所有比對項,而不僅僅是第一個比對項。經過多年不得不使用庫或手動編碼的解決方案,這是一個受歡迎的補充。
在示例1中,我例舉了一個簡單的示例,其中我們修改了一些莎士比亞作品。
示例1、 replaceAll()
let quote = "all the world's a stage, and all the men and women merely players";
let newQuote = quote.replaceAll("all", "most of");
console.log(newQuote);
promise.any()
promise.any() 方法接受一組承諾,并允許通過傳回一個新的承諾來響應第一個成功完成的promise。
如果任何promise被拒絕,它們将被忽略。(請注意此方法與 promise.all() 的對比,後者在任何錯誤或拒絕時停止;與 promise.allSettled() 相比,它可以讓您觀察在集合中解決的所有promise,即使存在中間錯誤。)
如果任何一個 Promise 出錯,promise.any() 仍然會根據集合中的第一個已解決的 Promise 進行操作。
如果傳入的 Promise 都沒有解析,則 promise.any() 方法傳回一個被拒絕的 Promise。它傳回的錯誤是 AggregateError,它也是 ECMAScript 2021 引入的一種新錯誤類型。AggregateError 表示遇到的所有錯誤的摘要。
我們可以使用 promise.any() 将多個 Promise 彙總為一個。該承諾将解決首先解決的集合,忽略錯誤和拒絕。
下面有一個簡單的示例。
示例2、promise.any()——全部解決
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "1 second");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, "2 second");
});
let promises = [promise1, promise2];
Promise.any(promises).then((firstResolved) => {
console.log(firstResolved); // outputs “1 second”
})
接着,我們開始看示例3,其中所有的 Promise 最終都因為被拒絕而失敗。
示例3、promise.any()——全部被拒絕
const promise1 = new Promise((resolve, reject) => {
setTimeout(reject, 1000, "1 second");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 2000, "2 second");
});
let promises = [promise1, promise2];
Promise.any(promises).then((firstResolved) => {
console.log(firstResolved);
}).catch((err) => { console.log("error: " + err) }) // outputs error: AggregateError: All promises were rejected
在示例3 中,我們添加了一個 catch 處理程式,它在兩個 Promise 都被拒絕後觸發。請注意,AggregateError 是一個包含有關失敗承諾的資訊的對象。
讓我們仔細看看 AggregateError,它是 ECMAScript 2021 中的另一個新特性。
AggregateError
AggregateError 是一種特殊的錯誤子類,它将許多錯誤組合成一個彙總對象。如您所見,特性 3 中的 promise.any() 方法建立了一個 AggregateError。
在該示例中,傳遞給 promise.any() 的所有promise都失敗了,是以該方法傳回了 AggregateError。錯誤包含描述錯誤的消息和包含有關每個錯誤的詳細資訊的數組。
但是在示例4 顯示了傳回的錯誤内容。
示例4、 AggregateError
AggregateError: All promises were rejected
errors: Array(2)
0: "1 second"
1: "2 second"
length: 2
message: "All promises were rejected"
stack: "AggregateError: All promises were rejected"
如上所示,AggregateError 可以通過 AggregateError.errors 通路導緻錯誤的承諾消息。
新的邏輯指派運算符
JavaScript 有熟悉的數學指派運算符,例如 +=,它可以一次性執行運算和指派,作為一種友善。ECMAScript 2021 為邏輯運算符 ||、?? 和 && 添加了類似的支援。
讓我們來看看其中的每一個。
空指派 (??=)
我們可以使用 nullish 指派運算符來測試變量是否為 null 或undefined。如果變量為 null 或undefined,我們可以将表達式的右側配置設定給變量。
接着,我們繼續看示例5中的一個示例。
示例5、 ??= 實際指派
let quote = "When goodness is lost there is morality.";
let existingQuote = "A leader is best when people barely know he exists";
let nonExistingQuote = null;
existingQuote ??= quote;
nonExistingQuote ??= quote;
console.log(existingQuote); // A leader is best when people barely know he exists
console.log(nonExistingQuote); // When goodness is lost there is morality.
請注意,當用于存在的變量時,例如 existingQuote,nullish 指派運算符什麼也不做。但是,當在 nonExistingQuote 上使用時,它會為報價配置設定一個新值。
即使existingQuote 的字元串為空(在JavaScript 中是一個假值),nullish 指派也不會替換它;它将保持為空字元串。這就是運算符的本質:它隻測試 null 或 undefined。
和指派 (&&=)
和指派運算符 (&&=) 測試表達式的左側。如果左側為真,則配置設定表達式的右側。如果它是假的,則操作員什麼也不做。
下面我們看特性6中的一個簡單的示例。
示例6、指派運算符 ( &&=)
和指派運算符 ( &&=)用于表達式的左側。如果左側不為null或undefined,則配置設定表達式的右側。如果它是假的,則什麼也不做。
let emptyString = "";
emptyString &&= "bar";
console.log (emptyString); // “”
let nonEmptyString = "foo";
nonEmptyString &&= "bar";
console.log(nonEmptyString); // “bar”
在特性6 中,第一個控制台日志輸出一個空字元串。這是因為空字元串是虛假的,是以 &&= 運算符不會為其配置設定新值。第二個控制台輸出“bar”。這是因為 nonEmptyString 是“foo”,這是一個真值。
&&= 是一種邊緣情況運算符,但在您需要時很有用。
或指派 (||=)
or 指派運算符與您剛剛看到的 and 指派運算符相反。我們可以使用清單 6 中的相同示例,這次将 &&= 替換為 ||=。
示例 7、||= 實際指派
let emptyString = "";
emptyString ||= "bar";
console.log (emptyString); // “bar”
let nonEmptyString = "foo";
nonEmptyString ||= "bar";
console.log(nonEmptyString); // “foo”
如果表達式的左側是假的,||= 指派運算符解析到右側。是以,在這種情況下,emptyString 變為“bar”。nonEmptyString 變量保持其真實值“foo”。
WeakRef
WeakRef 用于引用目标對象,而不會将其從垃圾收集中儲存。這是一個相當深奧的語言功能,工作編碼人員很少使用。WeakRef 的一個常見用例是實作大對象的緩存或映射,“不希望大對象僅僅因為它出現在緩存或映射中而保持活動狀态。”
是以,如果發現自己正在為大型實體建構緩存解決方案,請記住 WeakRef 存在。否則,如果不确定是否需要 WeakRef 變量引用,應該避免使用它。(規範本身建議避免使用。)
FinalizationRegistry
JavaScript 幾乎與 Java 棄用 Object.finalize() 幾乎同時引入了 FinalizationRegistry,這有點程式設計諷刺。這些特征實際上是相似的。與 WeakRef 一樣,規範警告開發人員遠離使用者定義的終結器。
但是,對于某些用例,新的 FinalizationRegistry 可能正是我們所需要的。該規範提供了消耗許多檔案句柄的長時間運作程序的示例。在這種情況下,使用 FinalizationRegistry 可以確定沒有句柄被洩露。
與 WeakRef 一起,FinalizationRegistry 更适合平台和架構開發人員的工具箱,而不是應用程式開發人員。
Numeric literal separators
數字分隔符是一種很好的方式,可以讓我們更輕松地檢視大量數字。JavaScript 不能像自然語言那樣使用逗号,因為那個符号已經被占用了。是以,ECMAScript 2021 引入了下劃線。
第一輸入方式:
let distanceToSun = 91772000000;
第二種輸入方式:
let distanceToSun = 91_772_000_000;
但是第二種方式更容易閱讀。
Array.prototype.sort improvements
這更像是一個注釋而不是一個功能。基本上,ECMAScript 2021 規範更準确地描述了 Array.prototype.sort 的工作原理。這種變化應該會減少引擎之間實作的差異。
寫在最後
以上就是全部内容,如果你覺得有用的話,記得點贊我,關注我,我将與你分享更多有用的内容。
祝程式設計愉快!
學習更多技能
請點選下方公衆号