ECMAScript 2025(ES2025)正式版:新增能力与采用建议
ES2025 是 ECMA-262 第 16 版,Ecma 于 2025 年 6 月 25 日批准该版本。本文聚焦这份语言规范中的正式能力;同年发布的 Intl.DurationFormat 属于独立的 ECMA-402 国际化规范,见后文附注。
年度标准快照、TC39 提案阶段和实际可用性是三件不同的事:提案进入 Stage 4 后才会纳入下一份年度标准,但浏览器、Node.js 与构建工具何时支持,仍取决于具体版本。上线前请以项目的目标运行时实际测试为准。
一览
| 场景 | 新能力 | 核心 API 或语法 |
|---|---|---|
| 比较、组合和筛选集合 | Set 集合运算 | union()、intersection()、difference() |
| 惰性处理可迭代数据 | 同步迭代器辅助方法 | Iterator.from()、map()、take()、toArray() |
| 统一同步与异步失败 | Promise 执行器 | Promise.try() |
| 存储或传输半精度数值 | Float16 支持 | Float16Array、Math.f16round() |
| 拼接动态正则 | 正则转义 | RegExp.escape() |
| 显式加载 JSON 模块 | 导入属性与 JSON Modules | with { type: 'json' } |
| 缩小正则标志作用域 | 内联修饰符 | (?i:...)、(?-i:...) |
| 统一不同分支的提取结果 | 重复命名捕获组 | 在互斥分支中重复命名 |
此外,ES2025 还调整了由全局直接 eval() 引入的 var 声明的重声明规则;这是面向历史脚本兼容性的语义修订,不是建议在新代码中使用 eval() 的理由。
1. Set:直接表达集合运算
过去常把 Set 转回数组,再用 filter() 实现交集或差集。现在可直接调用集合方法,返回新的 Set,不会修改原集合。
const frontend = new Set(['html', 'css', 'javascript']);
const required = new Set(['javascript', 'typescript']);
console.log(frontend.intersection(required)); // Set { 'javascript' }
console.log(frontend.union(required)); // Set { 'html', 'css', 'javascript', 'typescript' }
console.log(frontend.difference(required)); // Set { 'html', 'css' }
console.log(required.isSubsetOf(frontend)); // false
可用运算还包括 symmetricDifference();关系判断包括 isDisjointFrom()、isSubsetOf() 与 isSupersetOf()。方法接受 Set-like 对象,不限于原生 Set,但业务代码通常应传入真正的 Set 以保持语义清晰。
2. Iterator helpers:按需处理数据流
同步迭代器拥有 map()、filter()、flatMap()、take()、drop() 等辅助方法,以及 reduce()、some()、find()、toArray() 等终结方法。中间操作是惰性的:只有消费者请求下一个值时,源迭代器才会继续读取。
function* ids() {
yield* [1, 2, 3, 4, 5];
}
const result = Iterator.from(ids())
.filter((id) => id % 2 === 1)
.map((id) => id * 10)
.take(2)
.toArray();
console.log(result); // [10, 30]
它适合生成器、分页结果和可能很大的同步数据源;迭代器仍是一次性消费的。该组 API 不包含异步迭代器辅助方法,处理 async iterable 时继续使用 for await...of 或项目已支持的方案。
3. Promise.try():把同步异常转为 rejected Promise
Promise.try() 会立刻调用传入函数:正常返回值会成为 fulfilled Promise,抛出的异常会成为 rejected Promise。它适合在同一条 Promise 链中接入可能同步抛错的旧 API。
function parseSettings(text) {
return JSON.parse(text);
}
const settings = await Promise.try(() => parseSettings('{"theme":"dark"}'));
console.log(settings.theme); // 'dark'
它不会把函数调用延后到微任务;若需要延迟执行,应明确使用 queueMicrotask()、计时器或项目的任务调度机制。
4. Float16:半精度浮点数
ES2025 新增 Float16Array,并让 DataView 支持 getFloat16() / setFloat16();Math.f16round() 可把 Number 按 IEEE 754 binary16 的精度舍入。它适合与图形、机器学习或二进制协议交换半精度数据。
const samples = new Float16Array([1, 1.5, Math.PI]);
const view = new DataView(new ArrayBuffer(2));
view.setFloat16(0, samples[1], true);
console.log(view.getFloat16(0, true)); // 1.5
console.log(Math.f16round(Math.PI)); // 3.140625
半精度的数值范围和有效精度远小于普通 Number;不要把它用于金额、精确计数或未经误差评估的业务计算。
5. RegExp.escape():安全拼接动态文本
将用户输入或普通文本嵌入正则表达式前,需要按正则语法转义。RegExp.escape() 专门完成此事,避免手写转义遗漏元字符或在更大的模式中产生歧义。
const keyword = 'C++ (beginner)';
const pattern = new RegExp(`^${RegExp.escape(keyword)}$`, 'i');
console.log(pattern.test('c++ (beginner)')); // true
该方法只负责把文本变成可字面匹配的模式片段,不会替代对输入长度、业务语义或 ReDoS 风险的控制。
6. 导入属性与 JSON Modules
静态导入可用 with 明确说明模块类型;JSON 模块默认导出解析后的 JSON 值。
import messages from './messages.json' with { type: 'json' };
console.log(messages.welcome);
动态导入则在第二个参数传入属性:
const { default: messages } = await import('./messages.json', {
with: { type: 'json' },
});
语言规范定义了语法和模块语义,但加载 JSON 的具体支持还取决于浏览器、Node.js、打包器及其配置。迁移时应先确认构建链是否接受 with 语法,而不是把旧的 assert 写法与新写法混用。
7. 正则表达式:局部标志与重复命名捕获组
内联修饰符可以只对某一段模式开启或关闭 i、m、s 标志,避免为了局部需求影响整个正则。
const title = /^(?i:javascript) (?<level>beginner|advanced)$/;
console.log(title.test('JAVASCRIPT beginner')); // true
对于日期等格式不同、但业务字段相同的互斥分支,可以在不同分支里复用捕获组名称:
const date = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;
console.log(date.exec('08/2025').groups); // { year: '2025', month: '08' }
重复名称只允许出现在不会同时匹配的替代分支中;复杂模式应为每种输入格式补充测试,确认 groups 中的字段符合预期。
国际化附注:Intl.DurationFormat
Intl.DurationFormat 属于 ECMA-402 第 12 版(ECMAScript 2025 国际化 API 规范),与 ECMA-262 的语言能力分开发布。它可按语言区域格式化持续时间,适合界面展示。
const formatter = new Intl.DurationFormat('zh-CN', {
style: 'long',
});
console.log(formatter.format({ hours: 1, minutes: 30 }));
// '1 小时 30 分钟'
它用于显示,不用于持续时间的计算或存储;计算时仍应保留明确的单位和业务语义。
采用建议
- 根据目标浏览器、Node.js 和构建工具版本建立支持矩阵;不要只因 API 已写入年度标准就默认所有用户环境可用。
- 通过特性检测和渐进增强引入新 API;必要时使用已审查的 polyfill,或保留兼容实现。
- 使用迭代器辅助方法前确认一次性消费、惰性执行和异常传播符合原有流程;为无限或超大数据源避免调用
toArray()。 - 将 JSON Modules 与导入属性纳入打包、测试和生产部署的完整链路验证,尤其要检查开发服务器和 SSR 环境。
- 为正则动态输入、浮点边界、集合关系和国际化输出补充针对性测试。
评论