Skip to content

ECMAScript 2024 主要包含内容 WIP

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"

异步的原子等待

此操作仅适用于查看  SharedArrayBuffer  的  Int32Array  或  BigInt64Array 。

js
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);

读取线程正在睡眠并等待位置 0,该位置预计为  Avyukt 。 result.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 标志

可调整大小和可增长  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.groupBy  和  Map.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  中提取  resolve  和  reject

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

参考内容

MIT Licensed