ES12中新的JavaScript 语言特性

web前端开发

共 5519字,需浏览 12分钟

 ·

2022-05-24 06:43

英文 | https://www.infoworld.com/article/3658393/8-great-new-javascript-language-features-in-es12.html
翻译 | 杨小爱

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()——全部解决

 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 最终都因为被拒绝而失败。

示例3、promise.any()——全部被拒绝

 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

在示例3 中,我们添加了一个 catch 处理程序,它在两个 Promise 都被拒绝后触发。请注意,AggregateError 是一个包含有关失败承诺的信息的对象。

让我们仔细看看 AggregateError,它是 ECMAScript 2021 中的另一个新特性。

AggregateError 

AggregateError 是一种特殊的错误子类,它将许多错误组合成一个汇总对象。如您所见,特性 3 中的 promise.any() 方法创建了一个 AggregateError。

在该示例中,传递给 promise.any() 的所有promise都失败了,因此该方法返回了 AggregateError。错误包含描述错误的消息和包含有关每个错误的详细信息的数组。 

但是在示例4 显示了返回的错误内容。

示例4、 AggregateError

 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"

如上所示,AggregateError 可以通过 AggregateError.errors 访问导致错误的承诺消息。

新的逻辑赋值运算符

JavaScript 有熟悉的数学赋值运算符,例如 +=,它可以一次性执行运算和赋值,作为一种方便。ECMAScript 2021 为逻辑运算符 ||、?? 和 && 添加了类似的支持。

让我们来看看其中的每一个。

空赋值 (??=)

我们可以使用 nullish 赋值运算符来测试变量是否为 null 或undefined。如果变量为 null 或undefined,我们可以将表达式的右侧分配给变量。 

接着,我们继续看示例5中的一个示例。

示例5、 ??= 实际赋值

 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 existsconsole.log(nonExistingQuote); // When goodness is lost there is morality.

请注意,当用于存在的变量时,例如 existingQuote,nullish 赋值运算符什么也不做。但是,当在 nonExistingQuote 上使用时,它会为报价分配一个新值。

即使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 的工作原理。这种变化应该会减少引擎之间实现的差异。

写在最后

以上就是全部内容,如果你觉得有用的话,记得点赞我,关注我,我将与你分享更多有用的内容。

祝编程愉快!

学习更多技能

请点击下方公众号


浏览 11
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报