ES2024新特性:8个实用功能解析


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();  
  
// 使用示例  
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 或转译工具。