ES2024 与 ES2025 新特性落地(含版本纠偏)
面试常踩的版本坑:顶层 await 其实是 ES2022、装饰器还在 Stage 3、管道运算符仍 Stage 2 未落地;真正进正式版的是 groupBy/withResolvers/Set 方法/Iterator Helpers 等。
一句话概括
ES2024 和 ES2025 确实落地了一批”早该有”的实用 API,但面试里最容易翻车的是版本归属混乱:很多人把”顶层 await”说成 ES2024 新特性(其实它 2022 就进了),把”装饰器”和”管道运算符”当成已经正式落地的语法(其实一个 Stage 3、一个 Stage 2,浏览器都还没原生支持)。这篇文章帮你把哪些是真·正式版、哪些还在 Stage 提案理清楚,避免面试时吹了一个浏览器跑不起来的语法。
核心知识点
1. 先分清”已落地 vs 还在 Stage”(面试前提)
说白了,TC39 的提案要经历 Stage 1→2→3→4,只有到 Stage 4 并入当年正式版,才算”落地”。一张表记牢:
| 特性 | 状态 | 面试要点 |
|---|---|---|
| 顶层 await | ES2022 已落地 | 常被误归到 2024/2025 |
Object.groupBy / Map.groupBy | ES2024 已落地 | 没有 Array.groupBy |
Promise.withResolvers | ES2024 已落地 | 取代构造函数里取 resolve |
RegExp /v 标志 | ES2024 已落地 | 比 /u 更严格的 Unicode |
| Set 7 个方法 | ES2025 已落地 | union/intersection/difference 等 |
| Iterator Helpers | ES2025 已落地 | .map/.filter/.take 惰性链 |
| Import Attributes(JSON 模块) | ES2025 已落地 | with { type: 'json' } |
RegExp.escape / Promise.try | ES2025 已落地 | 动态正则转义 / 同步错误转 reject |
| 装饰器 | Stage 3 | TS 5.0+ 支持,浏览器未原生 |
管道运算符 |> | Stage 2 | 未进任何正式版,需 Babel |
using / await using | ES2026 即将 | 显式资源清理,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——面试分清楚”哪个版本、有没有原生支持”,比罗列特性名值钱得多。