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+新特性

