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();
}

参考内容

相关推荐
0__O2 小时前
细说 new Function
javascript
百锦再2 小时前
从 .NET 到 Java 的转型指南:详细学习路线与实践建议
android·java·前端·数据库·学习·.net·数据库架构
i小杨3 小时前
前端埋点(打点)方案
前端·状态模式
前端加油站3 小时前
时间转换那些事
前端·javascript
风清云淡_A3 小时前
【VUECLI】node.js打造自己的前端cli脚手架工具
前端·node.js
Never_Satisfied3 小时前
在JavaScript / Node.js中,SQLite异步查询函数实现
javascript·sqlite·node.js
YuspTLstar3 小时前
一文掌握Redux-toolkit核心原理
前端·react.js
云枫晖3 小时前
手写Promise-静态方法all和allSettled
前端·javascript
weixin_456904273 小时前
前端开发时npm install报错解决方案
前端·npm·node.js