2021 年 6 月 22 日,第 121 届 Ecma 国际(Ecma International)大会以远程会议形式召开。正式通过了 ES2021 标准。
这次又带来了哪些有趣的特性呢?让我们一起来了解下。
String.prototype.replaceAll()
相比于String.prototype.replace()
,如果不使用全局正则表达式,就无法替换字符串中子字符串的所有实例。只会替换第一次匹配的字符。现在可以用String.prototype.replaceAll()
替换全部字符串而不需要使用正则。
let str = "mike name is mike"; str.replace("mike", "tom"); // tom name is mike str.replace(/mike/g, "tom"); // tom name is tom str.replaceAll("mike", "tom"); // 🆕 tom name is tom
Promise.any()
当有任何一个 promise 状态变为成功 (fulfilled),就返回。当全部 promise 都 rejected,抛出一个 AggregateError 错误。
const p1 = new Promise((resolve, reject) => { setTimeout(() => resolve("p1"), 100); }); const p2 = new Promise((resolve, reject) => { setTimeout(() => resolve("p2"), 200); }); const p3 = new Promise((resolve, reject) => { setTimeout(() => resolve("p3"), 300); }); Promise.any([p1, p2, p3]) .then((first) => { // 任何一个promise完成(fulfilled),就返回 console.log(first); }) .catch((error) => { // 全部promise都rejected,抛出一个AggregateError错误 console.log(error); });
相似的 API
名字 | 描述 | |
---|---|---|
Promise.allSettled | 不会短路 | ES2020 |
Promise.all | 当有一个 rejected 就短路 | ES2015 |
Promise.race | 当有一个 rejected 或 fulfilled 就短路 | ES2015 |
Promise.any | 当有一个 fulfilled 就短路 | ES2021 |
WeakRefs
一般来说,在 JavaScript 中,对象的引用是强引用的,这意味着只要持有对象的引用,它就不会被垃圾回收。只有当该对象没有任何的强引用时, js 引擎垃圾回收器才会销毁该对象并且回收该对象所占的内存空间。
let obj = { a: 1, b: 2 }; // 只要我们访问 obj 对象,这个对象就不会被垃圾回收
但是 WeakRefs
可以创建一个弱引用,对象的弱引用是指当该对象应该被 js 引擎垃圾回收器回收时不会阻止垃圾回收器的回收行为。
weak_ref 实例具有一个方法 deref,该方法返回被引用的原始对象,如果原始对象已被回收,则返回 undefined 对象。
const weak_ref = new WeakRef({ name: "tom" }); let obj = weak_ref.deref(); if (obj) { console.log(obj.name); // tom }
CAUTION使用它们需要仔细考虑,尽量避免使用它们。
FinalizationRegistry 使用 FinalizationRegistry
对象可以在垃圾回收器回收对象时执行回调函数。
// 构建监听对象被垃圾回收器清除的回调 const fr = new FinalizationRegistry((heldValue) => { console.log(heldValue); }); const obj = {}; const token = {}; /** * @function 注册监听 * @param 需要监听的对象 * @param 需要合并的Grid * @param 取消监听用的标识符 */ fr.register(obj, "obj deleted!", token); /** * @function 取消监听 * @param 取消监听的对象 */ fr.unregister(token); // 可能很久以后,回调执行 // => obj deleted!
数值分割符
引入的数值分隔符使用_
(下划线)字符,在数值组之间提供分隔,提高数字的可读性。
let num1 = 1000000000; // 1000000000 let num2 = 1_000_000_000; // 🆕 1000000000 console.log(num1 === num2); // true let a = 1_1; // 11 let a = 1__1 // 错误,只允许一个下划线作为数字分隔符 let a = 1_; // 错误,分隔符不能在尾部 let a = _1; // 错误,分隔符不能在头部 Number(1_1); // 11 Number('1_1'); // NaN
CAUTION分隔符不能在尾部和头部,只能在数字之间,只允许一个下划线作为数字分隔符,不可连续。分隔符不影响数值的类型转换值,也无法在字符串转数值时被识别。
逻辑赋值运算符
逻辑赋值运算符,目的是提供简洁的写法。
a ||= b; // 等效于以下两种写法 // a || (a = b); a为false时执行右边 // if(!a) a = b; a &&= b; // 等效于以下两种写法 // a && (a = b); a为truth时执行右边 // if(a) a = b a ??= b; // 等效于以下两种写法 // a ?? (a = b); a为undefined或null时执行右边 // if(a === nudefined || a === null) a = b;
其中??
运算符只有左边是 undefined 或 null 才返回右边。
undefined ?? 1; // 1 null ?? 1; // 1 false ?? 1; // false 0 ?? 1; // 0 "" ?? 1; // "" NaN ?? 1; // NaN 2 ?? 1; // 2