ES17(ES2026)新特性

发布时间:预计 2026 年 6 月 截至当前时间点(2026-03),以下特性已在 TC39 达到 Stage 4,预计纳入 ES2026 正式标准。

1. Temporal(现代日期时间 API)

Temporal 是 ES2026 最重磅的特性,提供了全新的日期时间体系,取代饱受诟病的 Date

基本用法

// 获取当前时间(带时区)
const now = Temporal.Now.zonedDateTimeISO('Asia/Shanghai');
console.log(now.toString());
// 2026-03-25T14:30:00+08:00[Asia/Shanghai]

// 纯日期(不含时间和时区)
const date = Temporal.PlainDate.from('2026-03-25');
console.log(date.year, date.month, date.day); // 2026 3 25

// 纯时间
const time = Temporal.PlainTime.from('14:30:00');
console.log(time.hour, time.minute); // 14 30

日期计算

const today = Temporal.Now.plainDateISO();
const birthday = Temporal.PlainDate.from('2000-05-20');

// 计算两个日期之间的差距
const duration = today.since(birthday);
console.log(`${duration.years} 年 ${duration.months} 月 ${duration.days} 天`);

// 日期加减
const nextWeek = today.add({ days: 7 });
const lastMonth = today.subtract({ months: 1 });

时区处理

// 在不同时区之间转换
const meeting = Temporal.ZonedDateTime.from({
  year: 2026, month: 3, day: 25,
  hour: 10, minute: 0,
  timeZone: 'America/New_York'
});

const shanghaiTime = meeting.withTimeZone('Asia/Shanghai');
console.log(shanghaiTime.hour); // 22(纽约上午10点 = 上海晚上10点)

持续时间

const duration = Temporal.Duration.from({ hours: 1, minutes: 30 });
const total = duration.total('minutes');
console.log(total); // 90

为什么要用 Temporal 替代 Date?

痛点 Date Temporal
月份从 0 开始 new Date(2026, 0, 1) 是 1 月 PlainDate.from('2026-01-01')
可变对象 setMonth() 修改原对象 所有操作返回新对象
时区处理 几乎不支持 一等公民
日期计算 手动算毫秒 .add() / .since()
解析不一致 不同引擎行为不同 严格统一

2. Array.fromAsync()

从异步可迭代对象创建数组,类似同步的 Array.from()

async function* fetchPages() {
  yield { page: 1, data: ['a', 'b'] };
  yield { page: 2, data: ['c', 'd'] };
  yield { page: 3, data: ['e', 'f'] };
}

const pages = await Array.fromAsync(fetchPages());
console.log(pages);
// [{ page: 1, data: ['a','b'] }, { page: 2, data: ['c','d'] }, { page: 3, data: ['e','f'] }]

带映射函数

const names = await Array.fromAsync(fetchPages(), item => item.data);
console.log(names); // [['a','b'], ['c','d'], ['e','f']]

也支持 Promise 数组

const results = await Array.fromAsync([
  fetch('/api/1').then(r => r.json()),
  fetch('/api/2').then(r => r.json()),
  fetch('/api/3').then(r => r.json())
]);

3. Error.isError()

跨 Realm 安全检测一个值是否为 Error 对象:

Error.isError(new Error('x'));       // true
Error.isError(new TypeError('x'));   // true
Error.isError(new RangeError('x'));  // true

Error.isError({ message: 'x' });    // false
Error.isError('error');              // false
Error.isError(null);                 // false

为什么需要它?

// instanceof 在跨 iframe / realm 时失效
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const err = new iframe.contentWindow.Error('跨域错误');

err instanceof Error;    // false ❌
Error.isError(err);      // true  ✅

4. Math.sumPrecise()

对浮点数数组进行精确求和,避免累加误差:

// 传统累加有精度问题
[0.1, 0.2, 0.3].reduce((a, b) => a + b, 0);
// 0.6000000000000001

// 精确求和
Math.sumPrecise([0.1, 0.2, 0.3]);
// 0.6

使用场景

  • 财务金额合计
  • 科学计算
  • 统计汇总

5. Uint8Array Base64 / Hex 转换

Uint8Array 新增 Base64 和 Hex 编解码方法:

// 编码
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
console.log(bytes.toBase64());  // 'SGVsbG8='
console.log(bytes.toHex());    // '48656c6c6f'

// 解码
Uint8Array.fromBase64('SGVsbG8=');  // Uint8Array [72, 101, 108, 108, 111]
Uint8Array.fromHex('48656c6c6f');   // Uint8Array [72, 101, 108, 108, 111]

实际场景

// 文件内容转 Base64
const file = await fetch('/image.png').then(r => r.arrayBuffer());
const base64 = new Uint8Array(file).toBase64();

// Token / 密钥处理
const token = Uint8Array.fromBase64(jwtPayload);

6. Iterator Sequencing(迭代器连接)

将多个迭代器串联成一个:

function* a() { yield 1; yield 2; }
function* b() { yield 3; yield 4; }

const combined = Iterator.concat(a(), b());
console.log([...combined]); // [1, 2, 3, 4]

实际场景

// 合并多个数据源
const localData = getLocalIterator();
const remoteData = getRemoteIterator();
const allData = Iterator.concat(localData, remoteData);

for (const item of allData) {
  process(item);
}

7. JSON.parse source text access

JSON.parse 的 reviver 函数可以访问原始源文本,解决大数字精度丢失问题:

const json = '{"id": 12345678901234567890}';

const parsed = JSON.parse(json, (key, value, { source }) => {
  if (key === 'id') {
    console.log(source); // '12345678901234567890'(原始文本)
    return BigInt(source);
  }
  return value;
});

console.log(parsed.id); // 12345678901234567890n

为什么重要

  • 以前 reviver 拿到的 value 已经是解析后的 JS 数值,大数字已经丢精度了
  • 现在通过 source 可以拿到原始字符串,自行决定如何转换

8. Map.prototype.getOrInsert / getOrInsertComputed

简化"查找或插入"的常见模式:

const cache = new Map();

// 旧写法
if (!cache.has('key')) {
  cache.set('key', computeValue());
}
const val = cache.get('key');

// 新写法:一步到位
const val = cache.getOrInsert('key', defaultValue);

// 带计算函数
const val = cache.getOrInsertComputed('key', () => computeValue());

实际场景

// 分组统计
const groups = new Map();
for (const item of items) {
  const list = groups.getOrInsert(item.category, []);
  list.push(item);
}

总结

特性 说明 重要性
Temporal 全新日期时间体系,取代 Date ⭐⭐⭐⭐⭐
Array.fromAsync() 异步数据聚合为数组 ⭐⭐⭐⭐
Error.isError() 跨 Realm 安全检测 Error ⭐⭐⭐
Math.sumPrecise() 精确浮点求和 ⭐⭐⭐
Uint8Array Base64/Hex 二进制编解码 ⭐⭐⭐⭐
Iterator Sequencing 迭代器串联 ⭐⭐⭐
JSON.parse source access 解决大数字精度问题 ⭐⭐⭐
Map getOrInsert 简化查找或插入模式 ⭐⭐⭐⭐

ES17 的核心亮点无疑是 Temporal——它将彻底改变 JavaScript 处理日期时间的方式。其他特性则延续了"工程常见需求原生化"的趋势,让开发者写更少的样板代码。

ES6+新特性 文章被收录于专栏

包含ES6+新特性

全部评论

相关推荐

985柜员:开发还敢还叫,全部让自测就老实了
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务