文章

ES2024 与 ES2025 新特性落地(含版本纠偏)

面试常踩的版本坑:顶层 await 其实是 ES2022、装饰器还在 Stage 3、管道运算符仍 Stage 2 未落地;真正进正式版的是 groupBy/withResolvers/Set 方法/Iterator Helpers 等。

ES2024 与 ES2025 新特性落地(含版本纠偏)

一句话概括

ES2024 和 ES2025 确实落地了一批”早该有”的实用 API,但面试里最容易翻车的是版本归属混乱:很多人把”顶层 await”说成 ES2024 新特性(其实它 2022 就进了),把”装饰器”和”管道运算符”当成已经正式落地的语法(其实一个 Stage 3、一个 Stage 2,浏览器都还没原生支持)。这篇文章帮你把哪些是真·正式版、哪些还在 Stage 提案理清楚,避免面试时吹了一个浏览器跑不起来的语法。

核心知识点

1. 先分清”已落地 vs 还在 Stage”(面试前提)

说白了,TC39 的提案要经历 Stage 1→2→3→4,只有到 Stage 4 并入当年正式版,才算”落地”。一张表记牢:

特性状态面试要点
顶层 awaitES2022 已落地常被误归到 2024/2025
Object.groupBy / Map.groupByES2024 已落地没有 Array.groupBy
Promise.withResolversES2024 已落地取代构造函数里取 resolve
RegExp /v 标志ES2024 已落地比 /u 更严格的 Unicode
Set 7 个方法ES2025 已落地union/intersection/difference 等
Iterator HelpersES2025 已落地.map/.filter/.take 惰性链
Import Attributes(JSON 模块)ES2025 已落地with { type: 'json' }
RegExp.escape / Promise.tryES2025 已落地动态正则转义 / 同步错误转 reject
装饰器Stage 3TS 5.0+ 支持,浏览器未原生
管道运算符 |>Stage 2未进任何正式版,需 Babel
using / await usingES2026 即将显式资源清理,Stage 3 已定稿

记住这条就够用:ES2024 是”分组/聚合/正则增强”,ES2025 是”集合运算/迭代器/模块增强”,装饰器和管道都还没正式进门。

2. ES2024 真·落地:分组、resolvers、正则 /v

1
2
3
4
5
6
7
8
9
10
11
12
// ✅ Object.groupBy:按回调返回值把数组分组(返回的是 null 原型的普通对象)
const users = [
  { name: 'a', age: 20 },
  { name: 'b', age: 35 },
  { name: 'c', age: 28 },
];
const byGroup = Object.groupBy(users, u => (u.age >= 30 ? 'senior' : 'junior'));
// { junior: [{name:'a'...},{name:'c'...}], senior: [{name:'b'...}] }

// ✅ Promise.withResolvers:不用在构造函数里"偷"出 resolve/reject
const { promise, resolve, reject } = Promise.withResolvers();
// 老写法要在 new Promise((res, rej) => { resolve = res; reject = rej; }) 里赋值,别扭

注意:没有 Array.prototype.groupBy——最初提案是数组方法,但因 Web 兼容性问题被撤销,最终改为 Object/Map 上的静态方法。这是高频追问点。

3. ES2025 真·落地:Set 集合运算

以前求交集得 arr1.filter(x => arr2.includes(x)),现在 Set 原生支持,且不修改原集合、接受任意可迭代对象:

1
2
3
4
5
6
7
8
9
10
11
const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);
a.union(b);             // Set(6) {1,2,3,4,5,6}
a.intersection(b);      // Set(2) {3,4}
a.difference(b);        // Set(2) {1,2}(在 a 不在 b,注意不交换)
a.symmetricDifference(b);// Set(4) {1,2,5,6}
a.isSubsetOf(b);        // false
a.isDisjointFrom(b);    // false

// ❌ 常见误解:以为会改原集合
a; // Set(4) {1,2,3,4} —— 原样没动,返回的是新 Set

性能上比 filter + includes 的 O(n²) 数组扫描好得多,底层是 Set 的近似 O(1) 查找。

4. ES2025 真·落地:Iterator Helpers(惰性迭代)

数组有 .map/.filter,但迭代器/generator 一直没有。ES2025 给迭代器加了同样的一套,关键是惰性(lazy)——配合 take 可以安全处理无限序列:

1
2
3
4
5
6
7
8
9
10
11
function* range(n) {
  for (let i = 0; i < n; i++) yield i;
}
const r = range(1000)
  .filter(x => x % 2 === 0)
  .map(x => x * x)
  .take(5)        // 取前 5 个就停,后面不再计算
  .toArray();     // [0, 4, 16, 36, 64]

// 普通数组也能用:先取迭代器
[1, 2, 3, 4].values().filter(x => x % 2 === 1).toArray(); // [1, 3]

5. ES2025 真·落地:Import Attributes、RegExp.escape、Promise.try

1
2
3
4
5
6
7
8
9
10
11
12
13
// ✅ 直接 import JSON(以前必须靠打包器),with 是安全声明
import config from './config.json' with { type: 'json' };
const data = await import('./data.json', { with: { type: 'json' } });

// ✅ RegExp.escape:把用户输入当字面量处理,防止 . * 等被当成元字符
const query = 'gmail.com';
const re = new RegExp(RegExp.escape(query), 'i'); // 正确转义了点号

// ✅ Promise.try:同步抛错也转成 reject,一个 .catch 兜住同步+异步
Promise.try(() => {
  if (!userId) throw new Error('no id');        // 同步错误
  return fetch(`/api/${userId}`).then(r => r.json()); // 异步错误
}).catch(err => console.error(err)); // 两种情况都能捕获

6. 顶层 await:是 ES2022,不是 2024/2025

1
2
3
4
// ❌ 别在面试说"这是 ES2024 新特性"
// ✅ 正确:ES2022 引入,只能在 ES Module 顶层用
const config = await fetch('/config.json').then(r => r.json());
export default config; // 导入方会等这个 await 完成才继续执行

两个要点:只存在于模块顶层(脚本/CommonJS 不行);会暂停整个模块的执行——导入它的模块会等它 await 完,循环依赖容易死锁,别滥用。

7. 装饰器(Stage 3)与管道运算符(Stage 2):都没正式落地

这是面试最高频的”吹牛翻车点”,必须说清楚现状:

1
2
3
4
5
6
7
8
9
10
11
12
// ✅ 装饰器:TS 5.0+ 已原生支持(无需 flag),但浏览器/Node 无原生支持,仍需编译
function logged(value: any, context: ClassMethodDecoratorContext) {
  const name = String(context.name);
  return function (this: any, ...args: any[]) {
    console.log(`calling ${name}`);
    return value.apply(this, args);
  };
}
class Order { @logged pay(amount: number) {} }

// ❌ 管道运算符:目前 Stage 2 提案(Hack 风格),原生语法浏览器跑不了,需 Babel 转译
// const result = input |> String(%) |> %.trim() |> normalize(%); // 提案语法,未标准化

关于装饰器,进阶加分点:老式 experimentalDecorators(3 参:target/key/descriptor)和新标准(2 参:value/context)签名不兼容;NestJS、Angular 还在用老式;新标准目前不支持参数装饰器和 emitDecoratorMetadata,所以这些框架迁移成本高。

其实你每天都在用

  • Object.groupBy:后台表格按状态/类型分组、按日期分桶,再也不用自己写 reduce 分组
  • Promise.withResolvers:封装”外部事件触发 resolve”的场景,比如按钮点击后才 resolve 一个 Promise
  • Set 方法:权限校验 required.intersection(userPerms) 看是否满足、特性开关 defaults.union(overrides) 合并
  • Iterator Helpers:处理大文件/大数据的惰性管道,避免一次性生成超大中间数组
  • 顶层 await:模块初始化时拉取配置/连接数据库,等 ready 再 export
  • RegExp.escape:搜索框输入当正则用时必用,防用户输入 ./* 破坏正则

常见误解(FAQ)

❌ 误区一:”装饰器和管道运算符已经在 ES2024/2025 正式落地了,可以直接用原生语法”

错。装饰器目前是 Stage 3,TS 5.0+ 已经支持,但浏览器和 Node 都没有原生实现,生产环境必须经过 TS/Babel 编译;管道运算符 |> 还停在 Stage 2(Hack 风格),连正式版都不是,原生语法今天任何浏览器都跑不了。面试吹”原生可用”等于现场翻车。

❌ 误区二:”顶层 await 是 ES2024 的新特性”

错,它是 ES2022(ES13) 就进正式版了。只是常被和”现代 JS”一起提,容易记错年份。

❌ 误区三:”有 Array.groupBy 可以直接分组”

没有。原本的 Array.prototype.groupBy 因 Web 兼容性问题被撤销,最终落地的是 Object.groupBy 和 Map.groupBy 两个静态方法,且 Object.groupBy 返回的是 null 原型对象(不会意外继承到属性)。

❌ 误区四:”Set 的 union/intersection 会修改原集合”

不会。这 7 个方法全部返回新 Set,不修改调用者;而且参数接受任意可迭代对象(数组也行),不是只能传另一个 Set。

❌ 误区五:”用了新特性就不需要转译了”

取决于目标环境。面向现代浏览器/新 Node 可以免转译,但凡要兼容老浏览器或老构建链(尤其 with { type: 'json' }、Iterator Helpers 这类较新的),还是要配 Babel/TS 和对应的 targets 检查。

一句话总结

ES2024 落地了 groupBy/withResolvers//v,ES2025 落地了 Set 集合运算、Iterator Helpers、Import Attributes 等真·正式特性;但顶层 await 是 ES2022、装饰器仍在 Stage 3、管道运算符还停在 Stage 2——面试分清楚”哪个版本、有没有原生支持”,比罗列特性名值钱得多。

本文由作者按照 CC BY 4.0 进行授权