跳到主要内容

ECMAScript 2026(ES2026)完整新增能力

ES2026 是 ECMA-262 第 17 版,已于 2026 年 6 月获 Ecma 批准。它新增了 8 组语言能力,覆盖数值计算、迭代器、异步数据、错误识别、缓存、二进制与 JSON。下面按日常开发场景汇总这些 API;需要处理日期、时间和时区时,请阅读独立的 Temporal 专题

年度标准快照、TC39 提案阶段和运行时支持是三件不同的事:Stage 4 表示提案已完成,浏览器或 Node.js 是否可用仍取决于具体版本。本文只统计 ES2026 正式版 ECMA-262 的能力;Temporalusing / await usingAtomics.pause 等不计入这 8 项。权威清单见 ES2026 规范发布摘要ECMA-262 第 17 版

一览

场景新能力核心 API
降低浮点求和误差精确求和Math.sumPrecise()
延迟地拼接多个可迭代对象迭代器串接Iterator.concat()
统一收集异步来源异步转数组Array.fromAsync()
判断是否为真正的错误对象错误品牌检查Error.isError()
读取缓存时按需初始化Map / WeakMap upsertgetOrInsert()getOrInsertComputed()
在字节与 Base64/Hex 间转换二进制编解码Uint8Arrayfrom*to*setFrom*
无损读取 JSON 原始值JSON 源码访问reviver 的 context.source
控制 JSON 中原始值的输出原始 JSONJSON.rawJSON()JSON.isRawJSON()

1. Math.sumPrecise():汇总不同量级的数字

普通循环累加会受浮点精度影响,尤其是金额、统计值混合大数和小数时。Math.sumPrecise() 接收一个 Numbers 的可迭代对象,并尽量减少精度损失。

const values = [1e20, 1, -1e20];

console.log(values.reduce((sum, value) => sum + value, 0)); // 0
console.log(Math.sumPrecise(values)); // 1

它不替代货币的最小单位整数或十进制定点库;涉及金额时仍应先确定业务精度与舍入规则。

2. Iterator.concat():延迟地串接数据源

Iterator.concat() 按顺序消费任意可迭代对象,返回一个新的迭代器;相比先展开成数组,不必一次性分配全部内容。

const ids = Iterator.concat([1, 2], new Set([3, 4]), [5]);

console.log([...ids]); // [1, 2, 3, 4, 5]

输入会在前一个来源耗尽后才继续读取下一个来源,因此适合分页、生成器和大型数据流;调用后迭代器本身仍只能消费一次。

3. Array.fromAsync():收集异步可迭代数据

Array.fromAsync() 将 async iterable、同步 iterable 或 Promise-like 值来源转换为 Promise<Array>,并支持异步映射函数。

async function* pages() {
yield 'first';
yield 'second';
}

const labels = await Array.fromAsync(pages(), async (page, index) => {
return `${index + 1}: ${page}`;
});

console.log(labels); // ['1: first', '2: second']

它会收集全部结果后才 resolve;无限流或需要边到边处理的场景,应继续使用 for await...of

4. Error.isError():可靠识别 Error

instanceof Error 会受不同 Realm(例如 iframe)影响,Object.prototype.toString 也不适合做安全判断。Error.isError() 检查对象是否具有 Error 的内部品牌。

console.log(Error.isError(new TypeError('invalid input'))); // true
console.log(Error.isError({ name: 'Error', message: 'fake' })); // false

它只回答“是不是 Error 对象”;业务层仍应根据 name、错误码或自定义属性做具体处理。

5. Map 与 WeakMap:读取时初始化缓存

getOrInsert(key, value) 在键不存在时写入给定默认值,getOrInsertComputed(key, callback) 则只在缺失时调用回调生成值。两者都可用于 MapWeakMap

const counts = new Map();
counts.getOrInsert('ready', 0);

const metadata = new WeakMap();
const node = {};
const info = metadata.getOrInsertComputed(node, () => ({ visits: 0 }));
info.visits += 1;

对于 getOrInsert(),传入的默认值会在调用前就被创建;只有昂贵计算才使用 getOrInsertComputed()WeakMap 的键仍必须是对象或非注册 Symbol。

6. Uint8Array:原生 Base64 与 Hex

不再需要借助面向字符串的 atob() / btoa() 来处理二进制数据。ES2026 为 Uint8Array 提供静态解码、实例编码以及写入已有缓冲区的方法。

const bytes = Uint8Array.fromHex('48656c6c6f');

console.log(bytes.toBase64()); // 'SGVsbG8='
console.log(Uint8Array.fromBase64('SGVsbG8=').toHex()); // '48656c6c6f'

const target = new Uint8Array(5);
console.log(target.setFromHex('48656c6c6f')); // { read: 10, written: 5 }

完整 API 为 fromBase64()fromHex()toBase64()toHex()setFromBase64()setFromHex()。Base64 API 可通过选项选择 base64url 字母表、填充策略等;Hex 输出始终为小写。提案文档列出了选项和错误处理。

7. JSON.parse():访问原始 JSON 文本

reviver 现在接收第三个 context 参数。原始值未被修改时,context.source 保留对应的 JSON 源文本,可用于把超过安全整数范围的数字恢复为 BigInt

const source = '9007199254740993';
const value = JSON.parse(source, (key, parsed, context) => {
return key === '' ? BigInt(context.source) : parsed;
});

console.log(value); // 9007199254740993n

context.source 只为原始值提供,且应把它视为 JSON 片段而非可信代码;不要将其传给 eval 或拼接进 HTML。

8. JSON.rawJSON():原样序列化 JSON 原始值

JSON.rawJSON(text) 创建受规范约束的原始 JSON 值占位符,JSON.stringify() 会把其中的原始值文本嵌入输出。JSON.isRawJSON() 可检查一个值是否为这种占位符。

const order = {
id: JSON.rawJSON('9007199254740993'),
};

console.log(JSON.stringify(order));
// {"id":9007199254740993}

传入的文本必须是有效 JSON 原始值,不能是对象或数组;这能避免把任意片段注入 JSON。它常与 context.source 配合,用于保留大整数等会在普通解析中丢失的信息。JSON 源码访问提案提供了完整示例。

采用建议

  1. 先以目标浏览器和 Node.js 版本建立支持矩阵,再用特性检测或 polyfill 制定渐进增强方案。
  2. 新 API 不要直接替换所有旧代码:Array.fromAsync()Iterator.concat() 的内存与消费时机与数组操作不同。
  3. 为数值、二进制和 JSON 场景补充边界测试:大数、非法 Base64/Hex、缓冲区不足、JSON 原始片段及跨 Realm Error。

延伸阅读

评论