ECMAScript 2025(ES2025)于2025年6月正式发布,带来了一系列实用的新特性和改进。以下列举一些主要的特性:

导入属性(Import Attributes)

解决的问题:
之前无法直接将 JSON 文件作为模块导入,需要借助 Node.js 的 require 或其他工具函数。这使得在不同环境中处理 JSON 数据缺乏统一的标准方式。
现在提供了一种标准化的方式在导入模块时指定附加信息,如类型断言,确保导入的内容符合预期格式。
例如可以使用 import 语句导入 JSON 文件,并使用 with 关键字指定模块类型为 json。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 使用 import attributes 特性导入JSON
import config from './config.json' with { type: 'json' };

// 动态导入时使用属性
const dynamicModule = await import('./data.json', {
with: { type: 'json' }
});

console.log(config.environment); // 访问JSON内容
console.log(dynamicModule.default); // 访问动态导入的JSON内容

// 未来可能支持其他类型的模块
// import wasmModule from './module.wasm' with { type: 'webassembly' };
// import cssModule from './styles.css' with { type: 'css' };

迭代器辅助方法(Iterator Helpers)

解决的问题:
传统上,在处理迭代器时,如果想使用 map、filter 等方法,必须先转换为数组,这会消耗大量内存。
现在迭代器辅助方法提供了链式操作的能力,同时保持惰性求值的优势。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 旧方式 - 需要转换为数组,占用内存
const result1 = Array.from([1, 2, 3, 4, 5])
.filter(x => x % 2 === 0)
.map(x => x * 2);

// 新方式 - 直接在迭代器上操作,内存友好
const result2 = [1, 2, 3, 4, 5]
.values()
.filter(x => x % 2 === 0)
.map(x => x * 2)
.toArray();

// 使用其他迭代器方法
const filtered = [1, '', 2, null, 3, undefined, 4]
.values()
.filter(Boolean) // 过滤假值
.map(x => x * 2)
.take(3) // 只取前3个元素
.toArray();

console.log(filtered); // [2, 6, 8]

// 无限序列示例
function* fibonacci() {
let a = 0,
b = 1;
yield a;
yield b;
while (true) {
[a, b] = [b, a + b];
yield b;
}
}

const fib10 = fibonacci()
.drop(5) // 跳过前5个
.take(10) // 取接下来的10个
.toArray();

console.log(fib10); // [斐波那契数列中第5到15个数]

Set集合方法增强(New Set Methods)

解决的问题:
之前的 Set 对象缺少集合运算方法,开发者需要自己实现并集、交集、差集等操作,代码冗长且容易出错。
新增了7个集合方法包括:并集 union()、交集 intersection()、差集 difference()、对称差集 symmetricDifference()、子集判断 isSubsetOf()、超集判断 isSupersetOf()、不相交判断isDisjointFrom(),基于哈希表实现,性能高效。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);

// 并集
const union = setA.union(setB);
console.log([...union]); // [1, 2, 3, 4, 5, 6]

// 交集
const intersection = setA.intersection(setB);
console.log([...intersection]); // [3, 4]

// 差集
const difference = setA.difference(setB);
console.log([...difference]); // [1, 2]

// 对称差集(异或)
const symmetricDiff = setA.symmetricDifference(setB);
console.log([...symmetricDiff]); // [1, 2, 5, 6]

// 子集判断
const setC = new Set([1, 2]);
console.log(setC.isSubsetOf(setA)); // true

// 超集判断
console.log(setA.isSupersetOf(setC)); // true

// 不相交判断
const setD = new Set([7, 8, 9]);
console.log(setA.isDisjointFrom(setD)); // true (没有共同元素)

正则表达式增强

解决的问题:
包括三个方面的增强:RegExp.escape() 防止特殊字符被误解释,重复命名捕获组,以及内联修饰符,解决了复杂正则表达式的构建和维护问题。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 1. RegExp.escape() - 安全地将字符串转换为正则表达式片段
const userInput = 'How much does it cost? $50.00!'; // 用户输入可能包含特殊字符
const escapedInput = RegExp.escape(userInput);
const regex1 = new RegExp(`.*${escapedInput}.*`);
console.log(regex1.test('Prefix How much does it cost? $50.00! Suffix')); // true

// 2. 重复命名捕获组
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})-(?<day>\d{2})/;
const dateStr = '2025-03-15';
const match = dateStr.match(dateRegex);
console.log(match.groups.year); // 2025
console.log(match.groups.month); // 03 (第一个匹配的月份)

// 3. 内联修饰符 - 在模式内部设置标志
const caseInsensitiveHello = /^x(?i:hello)x$/; // 局部设置忽略大小写
console.log(caseInsensitiveHello.test('xHELLOx')); // true
console.log(caseInsensitiveHello.test('xHeLLox')); // true

// 也可以嵌套使用
const mixedFlags = /start(?i:case(?-i:sensitive))end/;
console.log(mixedFlags.test('startCASEsensitiveend')); // false
console.log(mixedFlags.test('startcasesensitiveend')); // true

Promise.try()

解决的问题:
之前同步函数抛出的错误无法直接被 Promise.catch 捕获,开发者通常需要额外的 try/catch 包裹统一同步和异步错误处理。
现在可以使用 Promise.try() 当函数可能同步抛出错误或异步产生错误时,提供一致的错误处理方式。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 一个可能同步抛出错误也可能返回 Promise 的函数
function riskyOperation(value) {
if (value < 0) {
throw new Error('Value cannot be negative');
}
if (value > 100) {
return Promise.resolve(value * 2);
}
return value * 2;
}

// 旧方式 - 需要额外处理同步错误
function handleWithTryCatch() {
try {
return Promise.resolve(riskyOperation(-5));
} catch (error) {
return Promise.reject(error);
}
}

// 新方式 - 统一使用Promise.try
Promise.try(() => riskyOperation(-5))
.then(result => console.log('Success:', result))
.catch(error => console.log('Error:', error.message));

Promise.try(() => riskyOperation(150)) // 返回Promise
.then(result => console.log('Async Success:', result))
.catch(error => console.log('Async Error:', error.message));

// 实际应用场景
function validateAndProcess(userData) {
// 可能同步验证失败
if (!userData.email || !userData.email.includes('@')) {
throw new Error('Invalid email');
}

// 或者异步处理
return fetch('/api/process-user', {
method: 'POST',
body: JSON.stringify(userData)
});
}

Promise.try(() => validateAndProcess({ email: 'invalid' }))
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Validation or API error:', error.message));

Float16支持(Float16Array, Math.f16round等)

解决的问题:
在图形处理、机器学习等领域,16位浮点数(半精度)比32位浮点数节省一半内存,提高了GPU操作和大数据处理的效率。

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 创建Float16数组
const f16Array = new Float16Array([1.5, 2.7, 3.14, 4.0, 5.5]);
console.log(f16Array[2]); // 3.140625 (由于精度限制)

// 使用DataView进行精确读写
const buffer = new ArrayBuffer(16);
const dataView = new DataView(buffer);

// 设置和获取Float16值
dataView.setFloat16(0, 3.14159, true); // 第三个参数表示是否小端序
const value = dataView.getFloat16(0, true);
console.log(value); // 3.140625

// 数学运算中的Float16舍入
const preciseValue = 3.141592653589793;
const roundedF16 = Math.f16round(preciseValue);
console.log(roundedF16); // 3.140625

// 在图像处理中的应用示例
function processImageData(imageData) {
// 将RGB值存储在Float16中以节省内存
const pixels = new Float16Array(imageData.length);

for (let i = 0; i < imageData.length; i++) {
pixels[i] = Math.f16round(imageData[i] / 255); // 归一化到[0,1]
}

return pixels;
}