ECMAScript 2024 主要包含内容 WIP
ECMAScript 2024 于 2024 年 6 月 22 日获得 ECMA International 的批准。
ECMAScript 是标准化的 JavaScript 语言,于 1997 年发布了第一版,现已发展成为世界上使用最广泛的通用编程语言之一。
本 Ecma 标准定义了 ECMAScript 2024 Language,是 ECMAScript 语言规范的第 15 版。
格式正确的 Unicode 字符串
此功能旨在改进 JavaScript 处理 Unicode 字符串的方式。
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
。
const sab = new SharedArrayBuffer(1024);
const int32 = new Int32Array(sab);
读取线程正在睡眠并等待位置 0
,该位置预计为 Avyukt
。 result.value
将是一个 Promise
。
const result = Atomics.waitAsync(int32, 0, "Avyukt", 1000);
// { async: true, value: Promise {<pending>} }
在读取线程或另一个线程中,调用内存位置 0,并且可以使用 "ok"
解析 Promise。
Atomics.notify(int32, 0);
// { async: true, value: Promise {<fulfilled>: 'ok'} }
正则表达式的 v 标志
可调整大小和可增长 ArrayBuffer
ArrayBuffer
启用了二进制数据的内存处理,并取得了巨大的成功。此提案扩展了 ArrayBuffer
构造函数以采用额外的最大长度,以允许缓冲区就地增长和缩小。同样, SharedArrayBuffer
被扩展以获取允许就地增长的额外最大长度。
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
实例,它允许对复杂键类型进行分组(想象一下复合键或元组)。
示例:
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
。
// ============= 提案前 =============
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 阶段。
应用程序编程接口
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();
}