ES12中新的JavaScript 語言特性
JavaScript 語言規(guī)范,也稱為 ECMAScript 或 ES,是一個動態(tài)文檔,每年都會根據(jù)不斷變化的需求進行修改。雖然 JavaScript 最初是一種腳本語言,但 ECMAScript 規(guī)范概述指出,該語言“現(xiàn)在被用于許多不同環(huán)境和規(guī)模的全方位編程任務。”因此,JavaScript 被更好地理解為一種功能齊全的通用用途的編程語言。
隨著即將發(fā)布的 ECMAScript 2022 版本即將發(fā)布,讓我們來看看 ECMAScript 2021 中引入的新 JavaScript 語言功能。
String.prototype.replaceAll
replaceAll() 方法將一個字符串或正則表達式(稱為模式)作為其第一個參數(shù)。第二個參數(shù)是模式的替換。給定第一個和第二個參數(shù),replaceAll() 返回一個新字符串,它將作為源字符串,其中模式的所有實例都被替換為替換。源字符串不受影響。
在 ECMAScript 2021 中,replaceAll() 與 ECMAScript 2020 的 matchAll() 一起改進了 JavaScript 內置 String 對象的固有功能。
replaceAll() 方法的工作方式與 replace() 完全相同,但適用于字符串中的所有匹配項,而不僅僅是第一個匹配項。經(jīng)過多年不得不使用庫或手動編碼的解決方案,這是一個受歡迎的補充。
在示例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() 仍然會根據(jù)集合中的第一個已解決的 Promise 進行操作。
如果傳入的 Promise 都沒有解析,則 promise.any() 方法返回一個被拒絕的 Promise。它返回的錯誤是 AggregateError,它也是 ECMAScript 2021 引入的一種新錯誤類型。AggregateError 表示遇到的所有錯誤的摘要。
我們可以使用 promise.any() 將多個 Promise 匯總為一個。該承諾將解決首先解決的集合,忽略錯誤和拒絕。
下面有一個簡單的示例。
示例2、promise.any()——全部解決
接著,我們開始看示例3,其中所有的 Promise 最終都因為被拒絕而失敗。
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.any()——全部被拒絕
在示例3 中,我們添加了一個 catch 處理程序,它在兩個 Promise 都被拒絕后觸發(fā)。請注意,AggregateError 是一個包含有關失敗承諾的信息的對象。
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
讓我們仔細看看 AggregateError,它是 ECMAScript 2021 中的另一個新特性。
AggregateError
AggregateError 是一種特殊的錯誤子類,它將許多錯誤組合成一個匯總對象。如您所見,特性 3 中的 promise.any() 方法創(chuàng)建了一個 AggregateError。
在該示例中,傳遞給 promise.any() 的所有promise都失敗了,因此該方法返回了 AggregateError。錯誤包含描述錯誤的消息和包含有關每個錯誤的詳細信息的數(shù)組。
但是在示例4 顯示了返回的錯誤內容。
示例4、 AggregateError
如上所示,AggregateError 可以通過 AggregateError.errors 訪問導致錯誤的承諾消息。
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"
新的邏輯賦值運算符
JavaScript 有熟悉的數(shù)學賦值運算符,例如 +=,它可以一次性執(zhí)行運算和賦值,作為一種方便。ECMAScript 2021 為邏輯運算符 ||、?? 和 && 添加了類似的支持。
讓我們來看看其中的每一個。
空賦值 (??=)
我們可以使用 nullish 賦值運算符來測試變量是否為 null 或undefined。如果變量為 null 或undefined,我們可以將表達式的右側分配給變量。
接著,我們繼續(xù)看示例5中的一個示例。
示例5、 ??= 實際賦值
請注意,當用于存在的變量時,例如 existingQuote,nullish 賦值運算符什么也不做。但是,當在 nonExistingQuote 上使用時,它會為報價分配一個新值。
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 的字符串為空(在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 變?yōu)椤癰ar”。nonEmptyString 變量保持其真實值“foo”。
WeakRef
WeakRef 用于引用目標對象,而不會將其從垃圾收集中保存。這是一個相當深奧的語言功能,工作編碼人員很少使用。WeakRef 的一個常見用例是實現(xiàn)大對象的緩存或映射,“不希望大對象僅僅因為它出現(xiàn)在緩存或映射中而保持活動狀態(tài)?!?
因此,如果發(fā)現(xiàn)自己正在為大型實體構建緩存解決方案,請記住 WeakRef 存在。否則,如果不確定是否需要 WeakRef 變量引用,應該避免使用它。(規(guī)范本身建議避免使用。)
FinalizationRegistry
JavaScript 幾乎與 Java 棄用 Object.finalize() 幾乎同時引入了 FinalizationRegistry,這有點編程諷刺。這些特征實際上是相似的。與 WeakRef 一樣,規(guī)范警告開發(fā)人員遠離用戶定義的終結器。
但是,對于某些用例,新的 FinalizationRegistry 可能正是我們所需要的。該規(guī)范提供了消耗許多文件句柄的長時間運行進程的示例。在這種情況下,使用 FinalizationRegistry 可以確保沒有句柄被泄露。
與 WeakRef 一起,F(xiàn)inalizationRegistry 更適合平臺和框架開發(fā)人員的工具箱,而不是應用程序開發(fā)人員。
Numeric literal separators
數(shù)字分隔符是一種很好的方式,可以讓我們更輕松地查看大量數(shù)字。JavaScript 不能像自然語言那樣使用逗號,因為那個符號已經(jīng)被占用了。因此,ECMAScript 2021 引入了下劃線。
第一輸入方式:
let distanceToSun = 91772000000;
第二種輸入方式:
let distanceToSun = 91_772_000_000;
但是第二種方式更容易閱讀。
Array.prototype.sort improvements
這更像是一個注釋而不是一個功能?;旧?,ECMAScript 2021 規(guī)范更準確地描述了 Array.prototype.sort 的工作原理。這種變化應該會減少引擎之間實現(xiàn)的差異。
寫在最后
以上就是全部內容,如果你覺得有用的話,記得點贊我,關注我,我將與你分享更多有用的內容。
祝編程愉快!