ECMA 大会批准发布 ECMAScript 2022:添加了什么新功能?
2022 年 6 月 22 日,ECMA 批准 ECMAScript 2022 语言规范 Ecma International approves new standards,意味着 ES2022 现在是正式的标准。
ECMAScript 2022 的编写者
参与这次发布的编写者是:
ECMAScript 2022 支持的新特性
类的新成员
class MyClass {
  instancePublicField = 1
  static staticPublicField = 2
  #instancePrivateField = 3
  static #staticPrivateField = 4
  #nonStaticPrivateMethod() {}
  get #nonStaticPrivateAccessor() {}
  set #nonStaticPrivateAccessor(value) {}
  static #staticPrivateMethod() {}
  static get #staticPrivateAccessor() {}
  static set #staticPrivateAccessor(value) {}
  static {
    // Static initialization block
  }
}
通过 in 操作符检查私有成员
私有成员检查也被称作“私有成员变量的类型构成检查(ergonomic brand checks for private fields)”。下面的表达式展示一次检查,该表达式确定 obj 是否拥有一个私有成员 #privateSlot:
#privateSlot in obj;
下面是实际使用范例:
class ClassWithPrivateSlot {
  #privateSlot = true
  static hasPrivateSlot(obj) {
    return #privateSlot in obj
  }
}
const obj1 = new ClassWithPrivateSlot()
assert.equal(ClassWithPrivateSlot.hasPrivateSlot(obj1), true)
const obj2 = {}
assert.equal(ClassWithPrivateSlot.hasPrivateSlot(obj2), false)
请注意我们只能够在私有成员声明的作用域内引用它。
模块中的顶层 await(Top-level await)
现在我们可以在 ES 模块的顶层直接使用 await 语法,并不仅仅限制在 async 函数或方法上:
// my-module.mjs
const response = await fetch('https://example.com')
const text = await response.text()
console.log(text)
error.cause
现在 Error 和它的子类可以标记造成的错误原因:
try {
  // 一些代码
} catch (otherError) {
  throw new Error('Something went wrong', { cause: otherError })
}
错误 err 的错误堆栈可以通过 err.cause 访问。
用于可索引的值获取的方法 .at()
方法 .at() 让我们通过索引读取变量的值(类似于中括号操作符 []),并且支持负值索引访问,这点与 [] 操作符不同:
['a', 'b', 'c'].at(0); // -> 'a'
['a', 'b', 'c'].at(-1) // -> 'c'
下面这些可索引的类型拥有方法 .at():
StringArray- 全部类数组的类:
Unit8Array等。 
正则表达式的索引匹配
如果我们在正则表达式中添加标记 /d,使用它就会产生匹配对象,记录着每个组捕获的开始和结束索引(行 A 和 B)。
const matchObj = /(a+)(b+)/d.exec('aaaabb')
assert.equal(matchObj[1], 'aaaa')
assert.deepEqual(
  matchObj.indices[1],
  [0, 4] // (A)
)
assert.equal(matchObj[2], 'bb')
assert.deepEqual(
  matchObj.indices[2],
  [4, 6] // (B)
)
Object.hasOwn(obj, propKey)
Object.hasOwn(obj, propKey) 是一种安全的检查对象 obj 是否拥有非继承的成员 propKey:
const proto = {
  protoProp: 'protoProp',
}
const obj = {
  __proto__: proto,
  objProp: 'objProp',
}
assert.equal('protoProp' in obj, true) // (A)
assert.equal(Object.hasOwn(obj, 'protoProp'), false) // (B)
assert.equal(Object.hasOwn(proto, 'protoProp'), true) // (C)
注意操作符 in 检查了继承属性(行 A),但是 Object.hasOwn() 仅仅检查了对象的自有属性(行 B 和 C)。
一些问题
JavaScript 与 ECMAScript 之间有什么不同?
- 通俗来说:
- JavaScript 是各种平台(诸如浏览器,Node.js,Deno 等)实现的编程语言。
 - ECMAScript 是语言标准,由 the ECMAScript language specification 描述声明。
 
 - 长篇讨论请看章节 “Standardizing JavaScript” in “JavaScript for impatient programmers”。
 
谁设计 ECMAScript?TC39 - Ecma Technical Committee 39
ECMAScript 是由标准组织 Ecma International 的技术委员会 39(Technical Committee 39 - TC39)设计的。
严格来说,其成员是公司:Adobe、Apple、Facebook、谷歌、微软、Mozilla、Opera、Twitter 和其他公司。也就是说,那些通常是竞争对手的公司正在共同研究 JavaScript。
每两个月,TC39 都会召开会议,由成员指定的代表和邀请的专家参加。这些会议的记录在 GitHub 存储库中公开。
在会议之外,TC39 还与 JavaScript 社区的各个成员和团体进行合作。
功能是如何添加进 ECMAScript?
新的 ECMAScript 功能必须向 TC39 提出。它们经历了几个阶段。
- 
从第 0 阶段(使 TC39 能够对提案发表意见)
 - 
到第 4 阶段(提议的特性已经准备好加入 ECMAScript)。
 - 
一旦某项功能达到第 4 阶段,它就被安排加入 ECMAScript 中。ECMAScript 版本的功能集通常在每年的 3 月被冻结。在该期限之后达到第四阶段的功能将被添加到明年的 ECMAScript 版本中。
 
ECMAScript 版本如何重要?
自从 TC39 程序建立以来,ECMAScript 版本的重要性已经大大降低。现在真正重要的是一个提议的功能处于什么阶段。一旦达到第四阶段,就可以安全使用了。但即使如此,你仍然要检查你所针对的引擎是否支持它。
“我最喜欢的功能建议”进展如何?
如果你想知道各种提议的功能处于什么阶段,请看 TC39 提案仓库。
我在哪里可以查到某个 ECMAScript 版本中增加了哪些功能?
我们有几个地方可以查到每个 ECMAScript 版本的新特性:
- 在“JavaScript for impatient programmers”中,有一节列出了每个 ECMAScript 版本中的新功能。它还提供了解释的链接。
 - TC39 资源库中有一个已完成提案的表格,其中说明了它们在哪个 ECMAScript 版本中被引入(或将被引入)。
 - ECMAScript 语言规范的“介绍”部分列出了每个 ECMAScript 版本的新特性。
 - ECMA-262 资源库有一个包含发布的版本页面。
 
本文由 吳文俊 翻译,原文地址 Ecma International approves ECMAScript 2022: What’s new?