尽管距离正式发布还有一段时间,ECMAScript 2026(简称 ES2026)的候选特性却已在开发者社区引发热烈讨论。多项“千年等一回”的语法糖与API终于进入 Stage 4,这意味着它们几乎笃定会出现在明年发布的规范中。许多前端工程师在社交媒体上发出同一声感慨:这些特性,真的早该这样了。

Set 终于学会了“集体行动”

长期以来,JavaScript 的 Set 数据结构虽然实用,却缺乏原生集合运算——无论是求交集、并集还是差集,开发者都得自己写循环或用 Array 转一道。这不仅让代码冗长,还容易因为引用类型比较而踩坑。

ES2026 将为 Set 补上 union()、intersection()、difference()、symmetricDifference()、isSubsetOf()、isSupersetOf() 和 isDisjointFrom() 七个方法。以 intersection 为例:

const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
a.intersection(b); // Set { 2, 3 }

这种简洁的声明式写法,让许多后端开发者感叹“其他语言早就有了”。对前端工程师而言,处理标签去重、权限交集等场景时,再也不必手动遍历。正如一位参与 TC39 讨论的社区代表所言:“Set 天生就该是个数学集合,现在它终于名副其实了。”

Array.fromAsync:异步数据流的“救兵”

随着流式 API(如 Fetch 的 Response.body、FileReader 等)的普及,从异步迭代器直接生成数组的需求愈发迫切。以往开发者不得不手动 for await...of 或借助第三方库,而 ES2026 将引入 Array.fromAsync() 静态方法:

const bytes = await Array.fromAsync(blob.stream());

该方法接受一个异步可迭代对象(或同步可迭代对象),返回一个 Promise,解析为包含所有值的数组。这一特性尤其利好流式数据处理场景——例如从大文件分片读取、实时日志聚合等。有工程师评论:“早该有原生方案了,之前用 async generator 转数组简直是在玩杂技。”

错误处理迎来“终极大法”

另一个令开发者振奋的进展是 Promise.try() 方法。它解决了长期以来的一个尴尬:当你想用 Promise 包裹一个同步函数,但又希望它被统一视作异步调用时,需要写 Promise.resolve().then(fn) 或者 new Promise(r => r(fn()))。前者无法捕获 fn 内的同步异常;后者则过于迂回。

Promise.try() 的设计直截了当——它接受一个函数或值,始终返回一个 Promise,且同步抛出的异常会自动转为 rejected 状态:

Promise.try(() => JSON.parse(jsonString))
  .then(data => handler(data))
  .catch(err => console.error(err));

这被众多面试官称为“早该有的语法糖”。它让混合同步/异步的代码变得更统一、更安全,尤其在自动化测试和中间件设计中价值凸显。

类型注解:一个温柔的“第一步”

尽管 TypeScript 已经占据主流,TC39 仍在推进 JavaScript 原生类型注解提案(进入 Stage 2)。ES2026 可能不会直接包含完整的类型系统,但允许开发者以注释形态标注类型,这些注释会被引擎忽略,却能提供给编辑器和 linter 使用。这意味着未来 JavaScript 开发者可以在不引入 TypeScript 编译步骤的前提下,享受部分类型提示。

社区反响:共识与审慎

“早该这样”并非贬义,而是开发者多年期盼终见落地的欣慰。不过也有声音提醒:新特性虽然好用,但生产环境往往需要等待主流浏览器和 Node.js 的支持。好在大部分 Set 方法和 Array.fromAsync 都可以通过 polyfill 降级,而 Promise.try 的 Babel 插件也已就绪。

TC39 每年一次的标准化节奏,让 JavaScript 从当年的“玩具语言”变得越来越厚重。ES2026 的这些新成员,没有颠覆性的新概念,却精准地堵住了开发者长期抱怨的“窟窿”。或许,这正是语言成熟的最佳标志——让每一次更新都让代码更短、更清晰、更接近直觉。

可以预见,当 ES2026 正式发布时,“早该这样”将成为整个社区的笑颜与一致评价。对于 JavaScript 的演进速度,除了感叹“终于来了”,我们更期待下一个“早该这样”。