ES2021-ES12 令人期待的新特性
前言
2021 年 3 月 13 日,ES2021 候選提案發布了其最終功能集的版本。如果它能夠在今年 6 月的 ECMA 大會上通過,就會成爲官方的標準!
這個候選提案提及到 ECMAScript 新特性如下所示:
-
String.prototype.replaceAll()
-
Promise.any
-
邏輯運算符和賦值表達式
-
數值分隔符
-
WeakRef and Finalizers
這些新的特性已經進入第四階段且已添加到谷歌 Chrome V8 引擎中。接下來我們來介紹下這些 ES2021 的新特性吧。
String.prototype.replaceAll()
const newString = oldString.replaceAll(pattern, replacement);
該方法返回一個新的字符串,所有 pattern
會被傳遞給它的replacement
替換。 其中pattern
參數可以是字符串或正則表達式,replacement
參數可以是字符串或針對每次匹配執行的函數。
replaceAll
方法是 String.replace 方法的續集,String.replace 僅替換pattern
的第一次找到的位置。
const str = "Linda is a self-taught developer.Linda will rule the world";
let newStr = str.replace("Linda","Micheal")
//output: Micheal is a self-taught developer.Linda will rule the world
let newStr = str.replaceAll("Linda","Micheal")
//output: Micheal is a self-taught developer.Micheal will rule the world
以往如果需要替換所有匹配項的話,就要寫成正則表達式,才能進行完全替換。
const str = "hello world, hello code";
const newStr = str.replace(/hello/g, "hi");
console.log(newStr); // "hi world, hi code"
現在有了String.prototype.replaceAll()
即便是輸入字符串也能完全替換匹配項。
const str = "hello world, hello code";
const newStr = str.replaceAll("hello", "hi");
console.log(newStr); // "hi world, hi code"
Promise.any
在 ES6 中引入了 Promise.race()
和 Promise.all()
方法,ES2020 加入了 Promise.allSettled()
。ES2021 又增加了一個使 Promise
處理更加容易的方法:Promise.any()
Promise 方法
Promise.any()
接收一個Promise
可迭代對象,只要其中的一個 promise
成功,就返回那個已經成功的 promise
(如示例 1 所示)。如果可迭代對象中沒有一個 promise
成功(即所有的 promise
都失敗 / 拒絕),就返回一個失敗的 promise
和AggregateError
類型的實例(如示例 2 所示),它是 Error
的一個子類,用於把單一的錯誤集合在一起。
Promise.any()
跟Promise.race()
方法很像,只有一點不同,就是不會因爲某個 Promise
變成 rejected 狀態而結束。
// 示例1
Promise.any([
new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
])
.then(value => console.log(`Result1: ${value}`))
.catch (err => console.log(err))
Promise.race([
new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
])
.then(value => console.log(`Result2: ${value}`))
.catch (err => console.log(err))
/**** Output ****/
// Third
// Result1: Second
上面代碼中,Promise.any()
方法的參數數組包含三個 Promise 操作。其中只要有一個變成fulfilled
,Promise.any()
返回的 Promise 對象就變成fulfilled
, 而Promise.race([p1, p2, p3])
裏面哪個結果獲得的快,就返回那個結果,不管結果本身是成功狀態還是失敗狀態。
如果沒有 fulfilled (成功的) promise,Promise.any()
返回 AggregateError
錯誤。
// 示例 2
const pErr1 = new Promise((resolve, reject) => {
reject('總是失敗1');
});
const pErr2 = new Promise((resolve, reject) => {
reject('總是失敗2');
});
Promise.any([pErr1,pErr2]).catch((err) => {
console.log(err);
})
/**** Output ****/
// "AggregateError: All promises were rejected"
邏輯運算符和賦值表達式(&&=,||=,??=)
在 JavaScript 中有許多賦值運算符和邏輯運算符,如以下基本示例:
// Assignment Operator Example
let num = 5
num+=10
console.log(num) // 15
// Logical Operator Example
let num1 = 6
let num2 = 3
console.log(num1 === 6 && num2 === 2) // false
console.log(num1 === 6 || num2 === 2) // true
新的提案讓我們將能把邏輯運算符和賦值運算符結合起來
1、帶有 && 運算符的邏輯賦值運算符
var x = 1;
var y = 2;
x &&= y;
console.log(x); // 2
第 3 行的操作等價爲:x && (x = y)
或者等價於
if(x) {
x = y
}
由於 x 是真實值,因此賦值了的值 y,即 2。簡而言之,運算符&&=
僅當 LHS 值爲真時,纔將 RHS 變量值賦給 LHS 變量。
2、帶有 || 的運算符邏輯賦值運算符
僅當 LHS 值爲假時,纔將 RHS 變量值賦給 LHS 變量。
// Logical Assignment Operator with || operator
let num1
let num2 = 10
num1 ||= num2
console.log(num1) // 10
// Line 4 can also be written as following ways
// 1. num1 || (num1 = num2)
// 2. if (!num1) num1 = num2
3、帶有?? 運算符的邏輯賦值運算符
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 4 can also be written as following ways
// num1 ?? (num1 = num2)
數值分隔符
我們將通過使用_(下劃線)字符在數字組之間提供分隔,使讀取數值更加容易,提高**可讀性**。
let x = 100_000; // 100000
數值分隔符也適用於 BigInt 數字。
const trillion = 1000_000_000_000n;
console.log(trillion.toString()); // "1000000000000"
分隔符僅出於可讀性目的。因此,它可以放置在數字中的任何位置。
const amount = 178_00;
console.log(amount.toString()); // "17800"
WeakRef and Finalizers
此功能包含兩個高級對象 WeakRef
和 FinalizationRegistry
。根據使用情況,這些接口可以單獨使用,也可以一起使用。官方建議不要輕易使用 WeakRef
和 finalizer
在 JavaScript 中,當你創建了一個創建對象的引用時,這個引用可以防止對象被垃圾收集,也就是說 JavaScript 無法刪除對象並釋放其內存。只要對該對象的引用一直存在,就可以使這個對象永遠存在。
ES2021 了新的類 WeakRefs
。允許創建對象的弱引用。這樣就能夠在跟蹤現有對象時不會阻止對其進行垃圾回收。對於緩存和對象映射非常有用。
必須用 new
關鍵字創建新的 WeakRef
,並把某些對象作爲參數放入括號中。當你想讀取引用(被引用的對象)時,可以通過在弱引用上調用 deref()
來實現。
const myWeakRef = new WeakRef({
name: '星野',
year: '25'
})
myWeakRef.deref()
// => { name: '星野', year: '25' }
myWeakRef.deref().name
// => '星野'
與 WeakRef
緊密相連的還有另一個功能,名爲 finalizers
或 FinalizationRegistry
。這個功能允許你註冊一個回調函數,這個回調函數將會在對象被垃圾回收時調用。
// 創建 FinalizationRegistry:
const reg = new FinalizationRegistry((val) => {
console.log(val)
})
(() => {
// 創建新對象:
const obj = {}
//爲 “obj” 對象註冊 finalizer:
//第一個參數:要爲其註冊 finalizer 的對象。
//第二個參數:上面定義的回調函數的值。
reg.register(obj, 'obj has been garbage-collected.')
})()
// 當 "obj" 被垃圾回收時輸出:
// 'obj has been garbage-collected.'
參考文章
-
ES2021 / ES12 New Features
-
Everything new coming in ES2021
-
JavaScript ES2021 Exciting Features
-
即將發佈的 ES2021(ES12)中有哪些有趣的功能
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/wh1RcA1-32rLI4xRaKi-uw