ECMAScript 2026 正式获批了,这 6 个新特性值得你现在就上手试试

ECMAScript 2026 正式获批了,这 6 个新特性值得你现在就上手试试

导语

就在上周,ECMA International 正式批准了 ECMAScript 2026——JavaScript 的第 17 个语言规范。你可能觉得每年一个新版本,不就是几个语法糖嘛。但这次不一样:Math.sumPrecise 解决了困扰开发者十几年的浮点数求和精度问题,Array.fromAsync 让异步数据流处理终于有了原生方案,Error.isError 让你跨 iframe、跨 Worker 也能准确判断错误类型。这 6 个特性不是”以后用得上”,而是你现在打开浏览器就能跑。

1. Math.sumPrecise():浮点数求和终于不再翻车了

先看一个经典名场面:

const prices = [19.99, 29.98, 9.99, 39.99, 14.99];
// 传统做法
console.log(prices.reduce((a, b) => a + b, 0));
// → 114.94000000000001  ❌

如果你的项目涉及金额计算,这种精度问题要么靠第三方库(如 decimal.js),要么靠乘以 100 转整数再除回来,要么加 toFixed(2) 糊弄过去。每个方案都有代价。

ES2026 的解法:

Math.sumPrecise([19.99, 29.98, 9.99, 39.99, 14.99]);
// → 114.94  ✅

Math.sumPrecise 内部使用 Kahan 求和算法,在累加过程中自动补偿浮点误差。它对数量级悬殊的数字效果尤其明显:

Math.sumPrecise([1e20, 0.1, -1e20]);
// → 0.1  ✅(传统循环做出来是 0)

注意: 它只求和,不解决乘除精度。0.1 + 0.2 的问题它也不管——因为 0.1 和 0.2 这两个字面量本身在二进制里就是不精确的。MDN 上写得很清楚:”the floating point literals 0.1 and 0.2 already represent mathematical values greater than 0.1 and 0.2″。

一句话判断: 只要你在做金额汇总、统计报表、大量 float 累计的场景,直接替换 reduceMath.sumPrecise

2. Array.fromAsync():从异步数据源构建数组

以前要把异步迭代器的数据收进数组,你得手写一个 for await...of 循环,或者用 Promise.all。现在一行搞定:

// 模拟异步生成器
async function* fetchPages() {
  for (let i = 1; i <= 3; i++) {
    yield await fetch(`/api/page/${i}`).then(r => r.json());
  }
}

// ES2026:一行收拢
const allData = await Array.fromAsync(fetchPages());

对比传统写法:

// 以前:手动循环
const results = [];
for await (const page of fetchPages()) {
  results.push(page);
}

Array.fromAsyncArray.from 的区别在于两点:

  • 它会依次等待每个元素兑现,不是并行
  • 如果传入的是 Promise 数组,它会逐个 await,而不是 Promise.all 那种全部并发

适用场景: 流式 API 响应、逐页分页拉取、文件逐行读取、数据库游标遍历。一句话——任何”边拿边处理”的数据,现在都能原生收尾。

3. Error.isError():跨 iframe、跨 Worker 也能精准判断错误

这是一个看似小但实际非常实用的特性。在 JavaScript 里,instanceof Error 跨执行上下文就失灵了:

// iframe 里的错误
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const iframeError = iframe.contentWindow.Error('来自 iframe 的错误');

console.log(iframeError instanceof Error);
// → false  ❌(踩过这个坑的举手)

ES2026 解法:

Error.isError(iframeError);
// → true  ✅

Error.isError 不依赖原型链判断,而是检查对象的内部标记,所以跨 Realm(iframe、Worker、跨域窗口)也能正确识别。底层实现类似于 Array.isArray 的逻辑。

为什么需要一个专门的方法?因为 try/catch 捕获到的东西可能是任何类型——字符串、对象、甚至 null。有了 Error.isError,你可以在全局错误处理器里精确过滤:

window.addEventListener('unhandledrejection', (event) => {
  if (Error.isError(event.reason)) {
    reportError(event.reason);
  } else {
    console.warn('非标准错误格式:', event.reason);
  }
});

4. Iterator.concat():多个迭代器连起来用

这个 API 语义很直白:把多个迭代器串成一串,挨个迭代完一个再接下一个。

const iter1 = [1, 2, 3].values();
const iter2 = [4, 5, 6].values();
const iter3 = [7, 8, 9].values();

const combined = Iterator.concat(iter1, iter2, iter3);
console.log([...combined]);
// → [1, 2, 3, 4, 5, 6, 7, 8, 9]

结合 ES2024 就已经落地的 Iterator Helpers.map().filter().take()),异步数据流的惰性处理链更完整了:

function* page1() { yield* [1, 2, 3]; }
function* page2() { yield* [4, 5, 6]; }

const result = Iterator.concat(page1(), page2())
  .map(x => x * 10)
  .take(5)
  .toArray();

console.log(result);
// → [10, 20, 30, 40, 50]

亮点: 惰性求值。不会创建中间数组,要多少算多少。大数据集下的内存优势非常明显。

5. Map/WeakMap 的缺失键默认值

这是一个”早该有了”的特性。之前从 Map 取不存在的键时,返回值是 undefined,你还得自行判空:

const scores = new Map([
  ['Alice', 95],
  ['Bob', 87]
]);

// 以前:判空靠手写
const bobScore = scores.get('Bob') ?? 0;       // 87
const charlieScore = scores.get('Charlie') ?? 0;  // 0

ES2026 给 Map.prototypeWeakMap.prototype 都新增了一个方法,支持在键不存在时返回默认值:

// ES2026:语义更清晰
const bobScore = scores.getOrDefault('Bob', 0);        // 87
const charlieScore = scores.getOrDefault('Charlie', 0); // 0

这看起来只是语法糖,但它减少了”忘记判空”的 bug 来源。结合 TypeScript,类型推导也更干净——你明确知道不可能返回 undefined

6. Uint8Array 的 Base64/Hex 编码原生支持

以前在前端做 Base64 编码,你通常得 btoa/atob 或者用 Buffer(Node.js 专属)。ES2026 直接把编码能力塞进了 Uint8Array

const bytes = new Uint8Array([72, 101, 108, 108, 111]);
// → "Hello"

bytes.toBase64();
// → "SGVsbG8="

bytes.toHex();
// → "48656c6c6f"

反过来也能解析:

Uint8Array.fromBase64('SGVsbG8=');
// → Uint8Array(5) [72, 101, 108, 108, 111]

Uint8Array.fromHex('48656c6c6f');
// → Uint8Array(5) [72, 101, 108, 108, 111]

直接受益场景: WebSocket 二进制消息、图片转 Base64 上传、Stream API 中的编码转换、服务端渲染中的 Buffer 替换。从此再也不需要在 Node.js 和浏览器之间来回切换编码方案了。

收尾:现在就能用,别等了

以上 6 个特性,来一个快速上手清单

| 特性 | 浏览器支持 | 重点场景 |

|——|———–|———|

| Math.sumPrecise | Chrome 144+/Firefox 130+ | 金额汇总、统计计算 |

| Array.fromAsync | Chrome 144+/Firefox 130+ | 流式数据、分页爬取 |

| Error.isError | Chrome 144+/Firefox 130+ | 全局错误处理、SDK 开发 |

| Iterator.concat | Chrome 144+/Firefox 130+ | 分页迭代、数据拼接 |

| Map getOrDefault | Chrome 144+/Firefox 130+ | 配置中心、缓存兜底 |

| Uint8Array base64 | Chrome 144+/Firefox 130+ | 二进制编码、图片处理 |

我的建议: 新项目直接放开用,Chrome 144+ 和 Firefox 130+ 已经覆盖了绝大多数用户。旧项目可以渐进式替换——先从 Math.sumPreciseError.isError 这种零风险的 API 开始。

你需要回退方案的话,core-js 已经提供了这些 API 的 polyfill,加上去就能放心跑。

ES2026 不是那种”看着挺好但用不了的”版本。它把 JavaScript 这些年的”窟窿”一个一个补上了。现在,是时候让代码更干净一点了。

评论区

0 条评论

登录后可评论。

查看完整榜单
查看完整榜单
查看完整榜单