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()——全部解决
接着,我们开始看示例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 都被拒绝后触发。请注意,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() 方法创建了一个 AggregateError。
在该示例中,传递给 promise.any() 的所有promise都失败了,因此该方法返回了 AggregateError。错误包含描述错误的消息和包含有关每个错误的详细信息的数组。
但是在示例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 有熟悉的数学赋值运算符,例如 +=,它可以一次性执行运算和赋值,作为一种方便。ECMAScript 2021 为逻辑运算符 ||、?? 和 && 添加了类似的支持。
让我们来看看其中的每一个。
空赋值 (??=)
我们可以使用 nullish 赋值运算符来测试变量是否为 null 或undefined。如果变量为 null 或undefined,我们可以将表达式的右侧分配给变量。
接着,我们继续看示例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 变为“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 的工作原理。这种变化应该会减少引擎之间实现的差异。
写在最后
以上就是全部内容,如果你觉得有用的话,记得点赞我,关注我,我将与你分享更多有用的内容。
祝编程愉快!