ECMA 2024(ES15) 新特性

ECMAScript 2024 主要包含内容:

ECMAScript 2024 于 2024 年 6 月 22 日获得 ECMA International 的批准。

ECMAScript 是标准化的 JavaScript 语言,于 1997 年发布了第一版,现已发展成为世界上使用最广泛的通用编程语言之一。

本 Ecma 标准定义了 ECMAScript 2024 Language,是 ECMAScript 语言规范的第 15 版。

格式正确的 Unicode 字符串

此功能旨在改进 JavaScript 处理 Unicode 字符串的方式。

js 复制代码
const str1 = "Bhaiya-G-Smile\uD83D\uDE00";  
const str2 = "No\uDC00Smile";  
  
console.log(str1.toWellFormed());  
// "Bhaiya-G-Smile😀"  
console.log(str2.toWellFormed());  
// "No�Smile"

异步的原子等待

此操作仅适用于查看 SharedArrayBufferInt32ArrayBigInt64Array

js 复制代码
const sab = new SharedArrayBuffer(1024);  
const int32 = new Int32Array(sab);

读取线程正在睡眠并等待位置 0,该位置预计为 Avyuktresult.value 将是一个 Promise

js 复制代码
const result = Atomics.waitAsync(int32, 0, "Avyukt", 1000);  
// { async: true, value: Promise {<pending>} }

在读取线程或另一个线程中,调用内存位置 0,并且可以使用 "ok" 解析 Promise。

js 复制代码
Atomics.notify(int32, 0);  
// { async: true, value: Promise {<fulfilled>: 'ok'} }

正则表达式的 v 标志

这是一个与传统 u(Unicode 模式)相关但更强大的模式。它主要解决了 Unicode 正则表达式在处理属性、集合和字符匹配时的歧义和局限性。

简单来说,v 标志提供了:

字符类集合的改进

允许在字符类中使用集合运算(并集、交集、差集)。

js 复制代码
// [\p{Letter}] 与 [\p{Number}] 的交集:即同时是字母和数字的字符
const regex = /^[\p{Letter}&&\p{Number}]$/v;

console.log(regex.test("A")); // false
console.log(regex.test("1")); // false
console.log(regex.test("٣")); // true (阿拉伯-印度数字 ٣,同时具备数值属性和字母属性)

简化的属性匹配

v 模式下,Unicode 属性匹配更严格、更一致。

js 复制代码
const letter = /^\p{Letter}+$/v;

console.log(letter.test("Hello")); // true
console.log(letter.test("123"));   // false

避免歧义

u 模式中,有些表达式会因为 Unicode 边界问题而导致意料之外的匹配行为,而 v 模式解决了这些问题。

js 复制代码
// u 模式下可能产生混淆
console.log(/\p{General_Category=Letter}/u.test("A")); // true
// v 模式下更规范
console.log(/\p{General_Category=Letter}/v.test("A")); // true

集合运算示例

js 复制代码
// 并集(union):
const regex = /^[\p{Letter}||\p{Number}]+$/v;
console.log(regex.test("Hello123")); // true
console.log(regex.test("!?"));       // false


// 差集(subtraction):
// 匹配所有字母,但排除 ASCII
const regex = /^[\p{Letter}--\p{ASCII}]+$/v;
console.log(regex.test("ñ")); // true
console.log(regex.test("A")); // false


// 交集(intersection):
// 同时属于 Letter 和 Uppercase 的字符
const regex = /^[\p{Letter}&&\p{Uppercase_Letter}]+$/v;
console.log(regex.test("A")); // true
console.log(regex.test("a")); // false

v 标志的出现让正则表达式在处理 Unicode 文本、国际化、集合操作 时更直观、更强大。它大大简化了过去依赖复杂模式才能完成的任务,对于需要处理多语言文本的开发者来说非常实用。

可调整大小和可增长 ArrayBuffer

ArrayBuffer 启用了二进制数据的内存处理,并取得了巨大的成功。此提案扩展了 ArrayBuffer 构造函数以采用额外的最大长度,以允许缓冲区就地增长和缩小。同样, SharedArrayBuffer 被扩展以获取允许就地增长的额外最大长度。

js 复制代码
let rab = new ArrayBuffer(1024, { maxByteLength: 1024 ** 2 });
// 0 offset, auto length
let U32a = new Uint32Array(rab);
assert(U32a.length === 256); // (1024 - 0) / 4
rab.resize(1024 * 2);
assert(U32a.length === 512); // (2048 - 0) / 4

// Non-0 offset, auto length
let U32b = new Uint32Array(rab, 256);
assert(U32b.length === 448); // (2048 - 256) / 4
rab.resize(1024);
assert(U32b.length === 192); // (1024 - 256) / 4

// Non-0 offset, fixed length
let U32c = new Uint32Array(rab, 128, 4);
assert(U32c.length === 4);
rab.resize(1024 * 2);
assert(U32c.length === 4);

// If a resize makes any accessible part of a TA OOB, the TA acts like
// it's been detached.
rab.resize(256);
assertThrows(() => U32b[0]);
assert(U32b.length === 0);
rab.resize(132);
// U32c can address rab[128] to rab[144]. Being partially OOB still makes
// it act like it's been detached.
assertThrows(() => U32c[0]);
assert(U32c.length === 0);
// Resizing the underlying buffer can bring a TA back into bounds.
// New memory is zeroed.
rab.resize(1024);
assert(U32b[0] === 0);
assert(U32b.length === 192);

数组分组

数组分组是一种极其常见的操作,最好的例子是 SQL 的 GROUP BY 子句和 MapReduce 编程(更好地认为是 map-group-reduce)。将类似数据组合成组的能力使开发人员能够计算更高阶的数据集,例如群组的平均年龄或网页的每日 LCP 值。

提供了两种方法: Object.groupByMap.groupBy 。第一个返回一个空原型对象,它允许符合人体工程学的解构并防止与全局对象属性发生意外冲突。第二个返回一个常规 Map 实例,它允许对复杂键类型进行分组(想象一下复合键或元组)。

示例:

js 复制代码
const array = [1, 2, 3, 4, 5];

// `Object.groupBy` 通过任意键对项目进行分组
// 在本例中,我们按偶数/奇数键进行分组
Object.groupBy(array, (num, index) => {
  return num % 2 === 0 ? 'even': 'odd';
});
// =>  { odd: [1, 3, 5], even: [2, 4] }

// `Map.groupBy` 返回Map中的项,用于使用对象键进行分组
const odd  = { odd: true };
const even = { even: true };
Map.groupBy(array, (num, index) => {
  return num % 2 === 0 ? even: odd;
});
// =>  Map { {odd: true}: [1, 3, 5], {even: true}: [2, 4] }

Promise.withResolvers

Promise.withResolvers 的目的是简化从 Promise 中提取 resolvereject

js 复制代码
// ============= 提案前 =============
let resolve = () => { };
let reject = () => { };

function request(type, message) {
  if (socket) {
    const promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });
    socket.emit(type, message);
    return promise;
  }

  return Promise.reject(new Error('Socket unavailable'));
}

socket.on('response', response => {
  if (response.status === 200) {
    resolve(response);
  }
  else {
    reject(new Error(response));
  }
});

socket.on('error', err => {
  reject(err);
});
// ============= 提案后 =============


const { promise, resolve, reject } = Promise.withResolvers()

function request(type, message) {
  if (socket) {
    socket.emit(type, message);
  }

  return reject(new Error('Socket unavailable'));
}

socket.on('response', response => {
  if (response.status === 200) {
    resolve(response);
  }
  else {
    reject(new Error(response));
  }
});

socket.on('error', err => {
  reject(err);
});

ArrayBuffer.prototype.transfer

ArrayBuffer 可以通过 HTML 的序列化算法进行传输和分离,但是缺少用于相同表达能力的编程 JS API。编程 API 对于编程模式很有用,例如转移 ArrayBuffer 的所有权、优化重新分配(即 realloc 语义)以及将可调整大小的 ArrayBuffer 固定为固定大小。长度的。该提案通过向 ArrayBuffer.prototype 添加新方法来填充这种表达能力。

该提案是从可调整大小的缓冲区提案中衍生出来的。在推出时,可调整大小的缓冲区处于第 3 阶段,该提案已降级到第 2 阶段。

应用程序编程接口

js 复制代码
class ArrayBuffer {
  // ... existing stuff

  // Returns a new ArrayBuffer with the same byte content
  // as this buffer for [0, min(this.byteLength, newByteLength)],
  // then detaches this buffer.
  //
  // The maximum byte length and thus the resizability of this buffer
  // is preserved in the new ArrayBuffer.
  //
  // Any new memory is zeroed.
  //
  // If newByteLength is undefined, it is set to this.bytelength.
  //
  // Designed to be implementable as a copy-free move or a realloc.
  //
  // Throws a RangeError unless all of the following are satisfied:
  // - 0 <= newByteLength
  // - If this buffer is resizable, newByteLength <= this.maxByteLength
  transfer(newByteLength);

  // Like transfer, except always returns a non-resizable ArrayBuffer.
  transferToFixedLength(newByteLength);

  // Returns whether this ArrayBuffer is detached.
  get detached();
}

参考内容

相关推荐
崔庆才丨静觅30 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax