2025 年 6 月 25 日,第 129 届 Ecma 大会批准了 ECMAScript 2025 语言规范。
本文将介绍 ECMAScript 2025 新增的语法和特性。
导入属性和 JSON 模块
导入属性提供了一个新的导入语法,可以用来指导入的模块类型,为导入非 JavaScript 模块提供了支持,第一个被支持的类型就是 JSON 模块。
// 静态导入
import configData1 from './config-data.json' with { type: 'json' };
// 动态导入
const configData2 = await import(
'./config-data.json', { with: { type: 'json' } }
);
with 关键字后面跟一个对象,这个对象包含 type 属性,用来指定导入的模块类型。
迭代器辅助方法
ECMAScript 2025 引入了 Iterator 类:
Iterator.from()方法可以创建一个迭代器。Iterator.prototype身上有很多迭代器的辅助方法,可以用来操作迭代器。
下面这些方法和同名的数组方法类似:
-
返回新的迭代器
iterator.filter(filterFn)iterator.map(mapFn)iterator.flatMap(mapFn)
-
返回
booleaniterator.some(someFn)iterator.every(everyFn)
-
返回其他值
iterator.find(findFn)iterator.reduce(reduceFn, initialValue)
-
无返回值
iterator.forEach(forEachFn)
还有一些迭代器独有的方法:
iterator.drop():返回一个新的迭代器,跳过指定数量的元素。iterator.take():返回一个新的迭代器,只取指定数量的元素。iterator.toArray():返回一个数组,包含迭代器的所有元素。
任何可迭代数据都可以使用上面的迭代器方法。迭代器方法不创建中间数组,也不增量计算数据,对于大量的数据迭代很有用:
迭代器方法与数组方法不同的是,使用迭代器方法时,所有方法都应用于迭代器的第一个值,然后应用于第二个值,以此类推。使用数组方法时,每一个方法都应用于所有值。其实可以理解为迭代器方法内部自动调了一次 next() 方法。
Set 的新方法
- 组合 Set
Set.prototype.intersection(otherSet):返回一个新的Set,包含两个Set的交集。Set.prototype.union(otherSet):返回一个新的Set,包含两个Set的并集。Set.prototype.difference(otherSet):返回一个新的Set,包含第一个Set中不属于第二个Set的元素。Set.prototype.symmetricDifference(otherSet):返回一个新的Set,包含两个Set的差集。
- 判断 Set 的关系
Set.prototype.isSubsetOf(otherSet):返回一个boolean,表示当前Set是否是另一个Set的子集。Set.prototype.isSupersetOf(otherSet):返回一个boolean,表示当前Set是否是另一个Set的超集。Set.prototype.isDisjointFrom(otherSet):返回一个boolean,表示当前Set是否与另一个Set无交集。
const set1 = new Set([1, 2, 3]);
const set2 = new Set([2, 3, 4]);
const intersection = set1.intersection(set2); // Set(2) {2, 3}
const union = set1.union(set2); // Set(4) {1, 2, 3, 4}
const difference = set1.difference(set2); // Set(1) {1}
const symmetricDifference = set1.symmetricDifference(set2); // Set(2) {1, 4}
const isSubsetOf = set1.isSubsetOf(set2); // false
const isSupersetOf = set1.isSupersetOf(set2); // false
const isDisjointFrom = set1.isDisjointFrom(set2); // false
RegExp.escape()
RegExp.escape() 方法可以用来转义文本,使其可以在正则表达式中使用。
function removeUnquotedText(str, text) {
const regExp = new RegExp(`(?<!“)${RegExp.escape(text)}(?!”)`, 'gu');
return str.replaceAll(regExp, '•');
}
console.log(removeUnquotedText('“yes” and yes and “yes”', 'yes')); // '“yes” and • and “yes”'
正则表达式的模式修饰符
正则表达式模式修饰符可以将正则标志应用于需要正则匹配的字符的某个部分。
例如
console.log(/^x(?i:HELLO)x$/.test('xHELLOx')); // true
console.log(/^x(?i:hello)x$/.test('xHELLOx')); // true
console.log(/^x(?i:HELLO)x$/.test('XhelloX')); // false
i 表示忽略大小写,上面的例子仅将i 作用于 hello 字符串,字符 x 则是不受影响。
重复命名的捕获组
命名捕获组(Named Capture Group) 是正则表达式中用来给捕获的子串起一个名字,便于后续读取。
const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = regex.exec('2025-06-28');
console.log(result.groups); // { year: '2025', month: '06', day: '28' }
重复命名捕获组则可以给多个捕获组起相同的名字,这样就可以在匹配时,一次性获取多个捕获组的值。
const RE = /(?<chars>a+)|(?<chars>b+)/v;
console.log(RE.exec('aaa').groups); // { chars: 'aaa' }
console.log(RE.exec('bbb').groups); // { chars: 'bbb' }
Promise.try()
Promise.try() 可以创建一个包含非异步功能的 Promise 链。
参数传递一个回调函数:
- 如果函数抛出异常,将返回带有异常的
reject - 如果函数返回一个值,
Promise.try()将该值解析为Promise(如果该值已经是Promise,则直接返回)。
function computeAsync() {
return Promise.try(() => {
const value = syncFuncMightThrow(); // (A)
return asyncFunc(value); // (B)
});
}
如果我们在 A 行调用的同步函数抛出异常,Promise.try() 捕获该异常并将其转换为被拒绝的 Promise。
支持 16 位的浮点数
Math.f16round()- 类型化数组的新元素类型
Float16ArrayDataView.prototype.getFloat16()DataView.prototype.setFloat16()