ES2021 帶來的新特性
ES2021(ES12)將會帶來 5 個(gè)新特性,本文將對這些新特性做一些簡單的介紹。
String.prototype.replaceAll()
在 JavaScript 中,通常會使用 String.prototype.replace() 方法來完成字符串的替換,例如:
'koofe'.replace('o', '?'); // k?ofe
在 String.prototype.replace() 方法中,當(dāng)?shù)谝粋€(gè)參數(shù)是字符串類型時(shí),只替換第一個(gè)匹配的字符串,相關(guān)細(xì)節(jié)可以參閱 MDN 文檔。因此,在上面的代碼中,只有第一個(gè) o 被替換成了 ?,第二個(gè) o 保持不變。如果要將匹配的字符串全部替換,只能通過正則表達(dá)式實(shí)現(xiàn),例如:
'koofe'.replace(/o/g, '?'); // k??fe
為了方便字符串的全局替換,ES2021 將支持 String.prototype.replaceAll() 方法,可以不用寫正則表達(dá)式就可以完成字符串的全局替換,例如:
'koofe'.replaceAll('o', '?'); // k??fe
Promise.any
Promise 支持以下幾種方法:
Promise.allSettled:無論每一個(gè) promise 是fulfilled 還是 rejected,返回值都是一個(gè) resolved promisePromise.allSettled([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));
// result:
// [{ status: "rejected", reason: 1 },
// { status: "fulfilled", value: 2 }]Promise.all: 只要有一個(gè) promise 是 rejected,則立即返回一個(gè) rejected promise;所有的 promise 都是 fulfilled 時(shí),則返回一個(gè) resolved promisePromise.all([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));
// error: 1Promise.race: 只要有 promise 是 fulfilled 或 rejected,則立即返回一個(gè) resolved 或 rejected promisePromise.race([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));
// error: 1Promise.any: 只要有一個(gè) promise 是 fulfilled 時(shí),則返回一個(gè) resolved promise;所有的 promise 都是 rejected 時(shí),則返回一個(gè) rejected promisePromise.any([
Promise.reject(1),
Promise.resolve(2)
])
.then(result => console.log('result:', result))
.catch(error => console.error('error:', error));
// result: 2
以上四個(gè)方法中,Promise.all 和 Promise.race 是 ES2015 中的特性,而 Promise.allSettled 和 Promise.any 分別是 ES2020 和 ES2021 中的特性。
邏輯賦值運(yùn)算符
邏輯賦值運(yùn)算符由邏輯運(yùn)算符和賦值表達(dá)式組合而成:
or or equals (||=)
a ||= b;
// 與 a ||= b 等價(jià)
a || (a = b);
// 與 a ||= b 等價(jià)
if (!a) {
a = b;
}and and equals (&&=)
a &&= b;
// 與 a &&= b 等價(jià)
a && (a = b);
// 與 a &&= b 等價(jià)
if (a) {
a = b;
}question question equals (??=)
a ??= b;
// 與 a ??= b 等價(jià)
a ?? (a = b);
// 與 a ??= b 等價(jià)
if (a === null || a === undefined) {
a = b;
}
用法示例:
let obj = {};
obj.x ??= 0;
console.log(obj.x) // 0
obj.x ||= 1;
console.log(obj.x) // 1
obj.x &&= 2;
console.log(obj.x) // 2
注意事項(xiàng):
a = a || b; // 與 a ||= b 不等價(jià)
a = a && b; // 與 a &&= b 不等價(jià)
a = a ?? b; // 與 a ??= b 不等價(jià)
不等價(jià)的原因是,無論上面的每個(gè)邏輯表達(dá)式結(jié)果如何,都會進(jìn)行賦值運(yùn)算;而邏輯賦值運(yùn)算符只會在條件成立的情況下進(jìn)行賦值,比如:
let x = 0;
const obj = {
get x() {
return x;
},
set x(value) {
console.log('setter called');
x = value;
}
};
// This always logs "setter called"
obj.x += 1;
assert.equal(obj.x, 1);
// Logical operators do not call setters unnecessarily
// This will not log.
obj.x ||= 2;
assert.equal(obj.x, 1);
// But setters are called if the operator does not short circuit
// "setter called"
obj.x &&= 3;
assert.equal(obj.x, 3);
數(shù)字分隔符
使用 _ 對數(shù)字進(jìn)行分割,提高數(shù)字的可讀性,例如在日常生活中數(shù)字通常是每三位數(shù)字之間會用 , 分割,以方便快速識別數(shù)字。在代碼中,也需要程序員較便捷的對數(shù)字進(jìn)行辨識:
// 1000000000 不易辨識
const count1 = 1000000000;
// 1_000_000_000 很直觀
const count2 = 1_000_000_000;
console.log(count1 === count2); // true
WeakRefs
WeakRef 實(shí)例可以作為對象的弱引用,對象的弱引用是指當(dāng)該對象應(yīng)該被 GC 回收時(shí)不會阻止 GC 的回收行為。而與此相反的,一個(gè)普通的引用(默認(rèn)是強(qiáng)引用)會將與之對應(yīng)的對象保存在內(nèi)存中。只有當(dāng)該對象沒有任何的強(qiáng)引用時(shí),JavaScript 引擎 GC 才會銷毀該對象并且回收該對象所占的內(nèi)存空間。因此,訪問弱引用指向的對象時(shí),很有可能會出現(xiàn)該對象已經(jīng)被回收,WeakRef 使用方法如下:
const ref = new WeakRef({ name: 'koofe' });
let obj = ref.deref();
if (obj) {
console.log(obj.name); // koofe
}
對于 WeakRef 對象的使用要慎重考慮,能不使用就盡量不要使用
總結(jié)
目前,ES2021 正處于 Stage 4 階段,也就是可以被納入到正式的 ECMAScript 語言規(guī)范中了,預(yù)計(jì)今年年中會被正式發(fā)布。本文介紹的這幾個(gè)新特性,在最新版本的 Chrome 瀏覽器中均已支持,感興趣的話可以快速體驗(yàn)一番。
