ECMAScript 2022 的新 JavaScript 功能(附示例)
ECMAScript 2022是对应今年的 ECMAScript 版本。它包含一些新功能,可以在我们的 JavaScript 项目中使用。如果您想了解ES2021,我已创建了下一篇博客文章:ECMAScript 2021 的新 JavaScript 功能(附示例)
今年的ECMAScript新功能包括:
- 顶级 await
- 私有实例字段、方法和访问器
- 静态类字段和方法
- 静态类初始化块
- 错误:.cause
- 数组、字符串和 TypedArray:.at() 方法
- 对象: .hasOwn()
- 正则表达式:匹配.indices('d' 标志)
顶级 await
在此之前,我们只能在 的范围内使用 await async functions
。这一直没问题,直到遇到问题,比如当我们到达模块顶层时,就无法使用 await 关键字了。现在,await
可以在模块的顶层使用,并且在初始化导入和创建回退时非常方便。
例子
旧的行为
当 async/await 功能首次引入时,尝试在异步函数之外使用 await 会导致语法错误 (SyntaxError)。许多开发者使用IIFE(立即调用函数表达式)作为替代方法来访问该功能。
await Promise.resolve(console.log('Hello World'));
// Output: SyntaxError: await is only valid in async function
// Alternative to fix the problem
(async function() {
await Promise.resolve(console.log('Hello World'));
// Output: Hello World
}());
新的行为
有了顶级等待,我们不需要使用更多的生活技巧。
await Promise.resolve(console.log('Hello World'));
// → Hello World
用例
动态依赖路径
const strings = await import(`/i18n/${navigator.language}`);
这允许模块使用运行时值来确定依赖关系。这对于开发/生产拆分、国际化、环境拆分等非常有用。
资源初始化
const connection = await dbConnector();
这允许模块代表资源,并且在模块永远无法使用的情况下产生错误。
依赖项回退
let jQuery;
try {
jQuery = await import('https://cdn-a.com/jQuery');
} catch {
jQuery = await import('https://cdn-b.com/jQuery');
}
私有实例字段、方法和访问器
以前,当需要声明私有方法或字段时,需要在方法名称的开头添加下划线(基于约定),但是,这并不能保证该方法是私有的。
ES2022添加了私有实例字段、方法和访问器等新功能。我们只需在方法名称开头添加#即可将其声明为私有的。
私有类字段
例子
class Test {
#firstName = 'test-name';
}
const test = new Test();
test.firstName
// Output: undefined
私有类方法
例子
class Test {
#addTestRunner(testRunner){
this.testRunner = testRunner
}
}
const test = new Test();
test.addTestRunner({name: 'test'});
// Output: TypeError: test.addTestRunner is not a function
私有访问器(getter 和 setter)
以前,需要声明 getter 或 setter 才能通过创建的实例进行访问,而 ES2022 添加了私有访问器作为新功能。
例子
class Test {
get #name(){
return 'test-name';
}
}
const test = new Test();
test.name
// Output: undefined
静态类字段和方法
静态类字段和方法不用于类的实例。相反,它们可以在类本身上调用,并使用static
关键字声明。
静态方法通常是实用函数和辅助函数,而静态属性对于缓存、固定配置或任何其他我们不需要在实例之间复制的数据很有用。
示例
静态类字段
class Test {
static firstName = 'test-static-name';
}
Test.firstName
// Output: test-static-name
静态类方法
class Test {
static greeting(){
console.log('Hello this is a greeting from a static method');
}
}
Test.greeting();
// Output: Hello this is a greeting from a static method
注意:在这些示例中,我们使用静态公共字段和方法,但是,我们也可以创建静态私有字段和方法。
静态类初始化块
此新功能提供了一种在类定义评估期间进行额外静态初始化的机制。
例子
class Test {
static numbers = [1,2,3,4,5,6];
static evenNumbers = [];
static oddNumbers = [];
// static class initialization block
static {
this.numbers.forEach((number) => {
if(!(number % 2) ) {
this.evenNumbers.push(number);
} else {
this.oddNumbers.push(number);
}
});
}
}
Test.evenNumbers;
// Output: [2, 4, 6]
Test.oddNumbers;
// Output: [1, 3, 5]
错误:.cause
Error及其子类现在允许我们指定错误背后的原因。有时,我们会捕获在更深层嵌套的函数调用中抛出的错误,并希望为其附加更多信息。
通过Error cause,我们可以为错误添加更多内在信息。要使用这个新功能,我们应该将错误选项指定为第二个参数,并使用cause键传递我们想要链接的错误。
例子
const getUsers = async(array)=> {
try {
const users = await fetch('https://myapi/myusersfake');
return users;
} catch (error) {
console.log('enter')
throw new Error('Something when wrong, please try again later', { cause: error })
}
}
try{
const users = await getUsers();
} catch(error) {
console.log(error); // Error: The array need a minimum of two elements
console.log(error.cause); // TypeError: Failed to fetch
}
数组、字符串和 TypedArray:.at() 方法
到目前为止,程序员们一直要求能够对 JS 数组进行负索引,就像在其他编程语言中一样。也就是说,要求能够写成arr[-1]而不是arr[arr.length-1],其中负数从最后一个元素开始倒数。
今年,随着ECMAScript 2022 的推出,我们有了一项重大变化,即一种帮助程序员进行负索引的新方法,即Array、String或TypedArray支持的.at()方法。
例子
访问数组和字符串的最新元素
旧的行为
const fruitsArray = ['banana', 'apple', 'orange', 'kiwi'];
console.log(fruitsArray[fruitsArray.length -1])
// Output: kiwi
const fruit = 'kiwi';
console.log(fruit[fruit.length -1])
// Output: i
新的行为
const fruitsArray = ['banana', 'apple', 'orange', 'kiwi'];
console.log(fruitsArray.at(-1))
// Output: kiwi
const fruit = 'kiwi';
console.log(fruit.at(-1))
// Output: i
注意:.at()也接受正数,因此在需要索引时可以将其用作另一种方式。
对象: .hasOwn()
如今,编写如下代码非常常见(尤其是在库代码中):
let hasOwnProperty = Object.prototype.hasOwnProperty
if (hasOwnProperty.call(object, "foo")) {
console.log("has property foo")
}
此新功能将代码简化为
if (Object.hasOwn(object, "foo")) {
console.log("has property foo")
}
正则表达式:匹配.indices('d' 标志)
新的/d 标志功能提供了有关输入字符串中每个匹配的开始和索引位置结束的一些附加信息。
例子
没有 /d 标志
const regexExample = /greeting(\d)/g;
const exampleString = 'greeting1greeting2';
const result = [...exampleString.matchAll(regexExample)];
console.log(result[0]);
输出
使用 /d 标志
const regexExample2022 = /greeting(\d)/dg;
const exampleString = 'greeting1greeting2';
const result = [...exampleString.matchAll(regexExample2022)];
console.log(result[0]);
输出
使用/d 标志,我们得到一个包含与正则表达式匹配的不同元素的索引的数组。
结论
JavaScript 是一门非常棒的编程语言。每年都会有一项很棒的新功能应用于我们的项目。在本文中,我们回顾了ES2022 的功能。我们期待明年推出新版本ES2023带来更多惊喜。如果您想了解ES2021的功能,我已为此撰写了下一篇博客文章:ECMAScript 2021 的新 JavaScript 功能(附示例)
请在评论中告诉我您的建议或其他可以添加的内容,我会根据这些内容更新帖子,谢谢!👍