JavaScript 作为一门不断发展的语言,每年都会引入新的特性来提升开发体验。
1. Promise.withResolvers()
这个新特性提供了一种更优雅的方式来创建和管理 Promise 的 resolve 和 reject 函数。
// 旧方式
let resolvePromise, rejectPromise;
const promise = new Promise((resolve, reject) => {
resolvePromise = resolve;
rejectPromise = reject;
});
// ES2024新方式
const { promise, resolve, reject } = Promise.withResolvers();
// 堆代码 duidaima.com
// 使用示例
async function executeTask() {
const { promise, resolve } = Promise.withResolvers();
startAsyncOperation(resolve);
return promise;
}
这个特性特别适合需要在 Promise 创建时机之外控制其状态的场景,比如实现事件触发器或复杂的异步流程控制。
2. ArrayBuffer.prototype.transfer()
这个方法允许我们高效地转移 ArrayBuffer 的所有权,避免内存复制。
const buffer = new ArrayBuffer(1024);
const transferred = buffer.transfer();
console.log(buffer.byteLength); // 0,原buffer被清空
console.log(transferred.byteLength); // 1024
// 在Web Workers间传输数据时特别有用
worker.postMessage(buffer.transfer());
这个功能在处理大型二进制数据时特别有价值,可以显著提升性能。
3. String.prototype.isWellFormed()和toWellFormed()
这两个方法用于处理字符串中的无效 Unicode 代理对。
const string = 'Hello\uD800World'; // 包含一个孤立的高代理项
console.log(string.isWellFormed()); // false
// 转换为规范形式
const wellFormed = string.toWellFormed(); // 替换无效字符
console.log(wellFormed.isWellFormed()); // true
这对于处理国际化应用和需要严格Unicode合规的场景非常有用。
4. 正则表达式中的v标志
v标志引入了更一致的转义序列规则,使正则表达式更可预测。
// 旧语法可能产生歧义
/\p{ASCII}/u.test('a'); // true
/\p{ASCII}/v.test('a'); // 语法错误,需要使用更明确的语法
// 新语法更加明确
/\p{ASCII_Hex_Digit}/v.test('A'); // true
/[\p{ASCII_Hex_Digit}]/v.test('A'); // true
5. Object.groupBy()和Map.groupBy()
这些新方法提供了一种简洁的方式来对数据进行分组。
const items = [
{ type: 'fruit', name: 'apple' },
{ type: 'vegetable', name: 'carrot' },
{ type: 'fruit', name: 'banana' }
];
const grouped = Object.groupBy(items, item => item.type);
console.log(grouped);
// {
// fruit: [
// { type: 'fruit', name: 'apple' },
// { type: 'fruit', name: 'banana' }
// ],
// vegetable: [
// { type: 'vegetable', name: 'carrot' }
// ]
// }
6. Atomics.waitAsync()
为 SharedArrayBuffer 提供了异步等待操作的能力。
const shared = new SharedArrayBuffer(4);
const int32 = new Int32Array(shared);
async function waitForChange() {
const result = await Atomics.waitAsync(int32, 0, 0);
console.log('Value changed:', result.value);
}
// 在另一个上下文中
Atomics.store(int32, 0, 42);
Atomics.notify(int32, 0);
7. 数组的扩展方法:toSorted(), toReversed(), toSpliced()
这些方法提供了不修改原数组的排序、反转和修改操作。
const numbers = [3, 1, 4, 1, 5];
// 不修改原数组的排序
const sorted = numbers.toSorted();
console.log(numbers); // [3, 1, 4, 1, 5]
console.log(sorted); // [1, 1, 3, 4, 5]
// 不修改原数组的反转
const reversed = numbers.toReversed();
console.log(numbers); // [3, 1, 4, 1, 5]
console.log(reversed); // [5, 1, 4, 1, 3]
// 不修改原数组的splice操作
const spliced = numbers.toSpliced(1, 2, 6, 7);
console.log(numbers); // [3, 1, 4, 1, 5]
console.log(spliced); // [3, 6, 7, 1, 5]
8. 新的常用数组方法
一些方便的数组操作方法被添加到规范中。
const array = [1, 2, 3, 4, 5];
// 查找最后一个满足条件的元素
const lastEven = array.findLast(x => x % 2 === 0); // 4
// 查找最后一个满足条件的元素的索引
const lastEvenIndex = array.findLastIndex(x => x % 2 === 0); // 3
// 检查数组是否全部相等
const allEqual = [1, 1, 1].every((x, _, arr) => x === arr[0]); // true
这些特性可以帮助我们编写更清晰、更高效的代码,不过,建议在使用这些新特性时使用相应的 polyfill 或转译工具。