2025 年 6 月 25 日,第 129 届 Ecma 大会正式批准了 ECMAScript 2025 的语言规范,这也意味着这个版本已经成为正式标准。
本文将带你快速了解 ECMAScript 2025 中最值得关注的几个新特性,掌握这些功能,你的 JavaScript 技能将再次进阶!
大家好,我是芝士,欢迎点此扫码加我微信 Hunyi32 交流,最近创建了一个低代码/前端工程化交流群,欢迎加我微信 Hunyi32 进群一起交流学习,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章
接下来就带着大家一一认识~
Import 属性与 JSON 模块支持
长期以来,开发者通过 fetch + JSON.parse
或 Webpack loader 来加载 .json
文件,现在你可以这样写了:
// 静态导入
import configData1 from './config-data.json' with { type: 'json' };
或者动态导入:
// 动态导入
const config = await import('./config.json', {
with: { type: 'json' }
});
ES2025 正式引入了 import attributes
,用于导入非 JavaScript 类型的模块,第一批支持的是 JSON
这为浏览器端模块生态注入了新的灵活性,未来也可能扩展到 CSS、WASM 等模块。
应用场景与示例
① 配置文件加载
用于加载构建环境、主题、自定义参数等前端配置文件:
// config.json
{
"apiBaseUrl": "https://api.example.com",
"theme": "dark"
}
// app.js
import config from './config.json' with { type: 'json' };
fetch(`${config.apiBaseUrl}/users`)
.then(res => res.json())
.then(console.log);
② 前端国际化资源(i18n JSON)
配合语言包 JSON 文件,实现多语言切换:
// en.json
{
"welcome": "Welcome",
"logout": "Log Out"
}
// zh.json
{
"welcome": "欢迎",
"logout": "退出登录"
}
// i18n.js
const lang = navigator.language.startsWith('zh') ? 'zh' : 'en';
const messages = await import(`./${lang}.json`, {
with: { type: 'json' }
});
document.getElementById('welcome').textContent = messages.default.welcome;
相信大家的项目中还有很多这样的场景可以用到!
迭代器辅助方法
你是否厌倦了频繁使用 Array.map().filter()
等数组链式调用? ES2025 引入了 迭代器辅助方法(Iterator Helpers),不仅语法更清晰,而且性能更优。
const arr = ['a', '', 'b', '', 'c', '', 'd', '', 'e'];
const result = arr.values() // 创建原生迭代器
.filter(x => x.length > 0)
.drop(1)
.take(3)
.map(x => `=${x}=`)
.toArray();
console.log(result); // ['=b=', '=c=', '=d=']
这些方法包括:
- 返回迭代器的方法:
.filter()
,.map()
,.flatMap()
- 返回布尔值:
.some()
,.every()
- 返回值:
.find()
,.reduce()
- 不返回值:
.forEach()
- 特有方法:
.drop(n)
,.take(n)
,.toArray()
其他迭代器辅助方法是迭代器独有的:
-
iterator.drop(limit)
返回不包含第一个limit元素的迭代器iterator。 -
iterator.take(limit)
返回包含 的第一个limit元素的迭代器iterator。 -
iterator.toArray()
iterator收集数组中所有剩余元素并返回它。
为什么它优于数组方法?
- 惰性执行:按元素逐一处理,不会创建中间数组。
- 兼容更广泛的数据结构:如 Set、Map。
- 节省内存与计算资源:适合处理大规模数据。
使用场景举例
处理日志、评论、通知等分页数据时,你可能不想一次性加载全部数据。使用迭代器可以流式处理分页内容,避免性能开销:
// 假设 logs 是一个大数组,每页最多显示 10 条非空记录,跳过前 5 条
function getPageLogs(logs, skip = 0, limit = 10) {
return logs.values()
.filter(item => item?.trim()) // 忽略空内容
.drop(skip)
.take(limit)
.map(line => `[LOG] ${line}`)
.toArray();
}
const logs = [
'', '启动中', '', '初始化', '成功登录', '',
'接收消息', '处理消息', '完成', '', '关闭连接'
];
console.log(getPageLogs(logs, 2, 5));
// 输出:['[LOG] 初始化', '[LOG] 成功登录', '[LOG] 接收消息', '[LOG] 处理消息', '[LOG] 完成']
Set 新增集合操作方法
操作 Set 数据结构更方便了,ES2025 新增了一系列集合运算方法:
const a = new Set([1, 2]);
const b = new Set([2, 3]);
a.union(b); // 并集 Set {1, 2, 3}
a.intersection(b); // 交集 Set {2}
a.difference(b); // 差集 Set {1}
a.symmetricDifference(b); // 对称差集 Set {1, 3}
a.isSubsetOf(new Set([1, 2, 3]));
// 是否为子集 true
集合组合运算:
union(other)
:
并集(合并两个集合,不重复),可使用于:合并用户标签、兴趣、权限来源等。
intersection(other)
:交集(保留两个集合共有的元素)
difference(other)
:差集(返回只存在于当前集合、不在 other 中的元素)
symmetricDifference(other)
:对称差集(两者中各自独有的元素)
关系判断方法:
-
isSubsetOf()
:是否为子集(当前集合的所有元素都包含在 other 中) -
isSupersetOf()
:是否为超集(other 的所有元素都在当前集合中) -
isDisjointFrom()
:是否无交集(两个集合没有任何重合元素)
正则表达式
RegExp.escape()
一个小而美的实用函数,用于将普通字符串转换为合法的正则表达式:
举个例子:
const keyword = '.?*';
const re = new RegExp(keyword, 'g'); // ❌ 报错:invalid regular expression
用户输入如果包含正则特殊字符(如 . * ? + ( ) [ ] { } ^ $ | \
等),就可能导致正则语法错误或匹配行为异常,甚至可能被恶意利用。使用 RegExp.escape()
,可解决问题:
RegExp.escape('.?*'); // => '\\.\\?\\*'
可以配合 RegExp 动态生成表达式时避免转义烦恼:
function safeSearch(str, keyword) {
const re = new RegExp(RegExp.escape(keyword), 'g');
return str.replaceAll(re, '🔍');
}
内联修饰符
/^x(?i:HELLO)x$/.test('xHELLOx'); // true
/^x(?i:HELLO)x$/.test('xhellox'); // true
/^x(?i:HELLO)x$/.test('XhelloX'); // false
仅在部分模式中启用大小写不敏感匹配,避免影响整体表达式。
命名重复捕获组
以前正则命名捕获组只能出现一次,现在可以在不同分支里重复命名了:
const RE = /(?<value>a+)|(?<value>b+)/v;
RE.exec('aaa').groups.value; // => 'aaa'
RE.exec('bb').groups.value; // => 'bb'
多个分支共享捕获名称,更易编写兼容多格式的解析器或提取器。 这让正则写法更加灵活、可维护。
Promise.try()
你是否经常写出这样的混合代码?
try {
const val = syncMayThrow();
await asyncOp(val);
} catch (err) {
handleError(err);
}
现在可以一行搞定,Promise.try()
用于统一同步/异步代码的错误处理逻辑:
Promise.try(() => {
const val = syncMayThrow();
return asyncOp(val);
}).catch(handleError);
它的作用类似于把同步代码也纳入 Promise 链中,简化异常处理!
支持 16 位浮点数
针对AI 模型/ 图像处理 / WebGPU 优化的数据类型,终于支持了:
const f16 = new Float16Array([1.0, 0.5, 0.25]);
console.log(f16); // Float16Array(3) [1, 0.5, 0.25]
const dv = new DataView(new ArrayBuffer(2));
dv.setFloat16(0, 3.1415);
console.log(dv.getFloat16(0)); // 3.140625(近似值)
新增支持包括:
-
Math.f16round()
:将任意数字转换为 Float16 精度 -
Float16Array
:16 位浮点数的数组视图,用于存储大量低精度浮点数,节省一半内存空间 -
DataView.prototype.getFloat16()
:从二进制缓冲区读取 Float16 编码值 -
DataView.prototype.setFloat16()
:向任意二进制缓冲区写入 Float16 格式的值
大家好,我是芝士,欢迎点此扫码加我微信 Hunyi32 交流,最近创建了一个低代码/前端工程化交流群,欢迎加我微信 Hunyi32 进群一起交流学习,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章
喜欢尝鲜的小伙伴,赶快用起来吧!