前言
截至2026年5月,ES2026(即 ECMAScript 2026)已正式发布,并引入多项重要特性,显著提升 JavaScript 在日期处理、不可变数据、资源管理等方面的能力。
Temporal:
日期时间 API,解决原生Date对象存在可变性、时区支持弱、API 不直观,需要借助第三方插件解决的格式化和时间计算等问题。
Temporal.PlainDate:纯日期(无时区)Temporal.ZonedDateTime:带时区的完整时间戳Temporal.Duration:表示时长(如“30天” ≠ “30×24小时”)
应用示例
const now = Temporal.Now.zonedDateTimeISO('Asia/Shanghai'); const nextWeek = Temporal.PlainDate.from('2026-05-13').add({ days: 7 });Records & Tuples
原生不可变值类型,解决JavaScript 对象/数组为引用类型,易被意外修改,且无法直接值比较的问题。
//Record(不可变对象):用 #{} 定义 const user = #{ name: "张三", age: 25 }; //Tuple(不可变数组):用 #[] 定义 const nums = #[1, 2, 3]; //修改值,如user.name= "李四"会报错using / await using
显式资源管理,解决Promise.all没考虑"取消"的情况下,带了的无主请求乱飞,已经没人等但还没释放"的查询把数据库连接池填满,Ctrl-C 之后端口被占用等种种问题。
using,同步资源的自动释放。
using temp = new TempFile("temp.txt");await using,异步资源的自动释放。
await using db = new DBConnection(); // 函数结束自动释放连接任何实现了[Symbol.asyncDispose]()方法的对象,可以用await using声明。当所在代码块退出时,不管是正常 return、抛异常、还是被上层的 AbortSignal 中断,运行时会自动调用并 await 这个方法。
注意:同一代码块里多个await using声明,会按后进先出(LIFO)的顺序清理。
后声明的资源可能依赖先声明的,反过来清理才对。对于临时需要聚合多个资源的场景,用AsyncDisposableStack。
async function withCleanup() { await using stack = new AsyncDisposableStack(); const conn = stack.use(await openConnection()); stack.defer(async () => await logCompletion()); // 两个清理动作都会跑,按注册的倒序 return conn.query('...'); }结合AbortSignal.any()组合取消信号,给异步操作装一个总闸。
它接受一个 AbortSignal 数组,返回一个新信号,任何一个输入信号触发,新信号就触发。这个 fetch 会在用户取消(controller.abort())或 5 秒超时时中止,以先到者为准。
const controller = new AbortController(); const timeoutSignal = AbortSignal.timeout(5000); const combined = AbortSignal.any([controller.signal, timeoutSignal]); const response = await fetch(url, { signal: combined });有了await using和AbortSignal.any(),可以搭一个轻量的任务作用域抽象。
class TaskScope { constructor() { this.controller = new AbortController(); this.signal = this.controller.signal; this.tasks = []; } spawn(fn) { const task = fn(this.signal).catch((err) => { if (err.name !== 'AbortError') { this.controller.abort(err); } throw err; }); this.tasks.push(task); return task; } async [Symbol.asyncDispose]() { this.controller.abort(); await Promise.allSettled(this.tasks); } } async function loadDashboard(userId, parentSignal) { const combinedSignal = AbortSignal.any([ parentSignal, AbortSignal.timeout(8000), ]); await using scope = new TaskScope(); const [user, settings, notifications] = await Promise.all([ scope.spawn((sig) => fetchUser(userId, sig)), scope.spawn((sig) => fetchSettings(userId, sig)), scope.spawn((sig) => fetchNotifications(userId, sig)), ]); return { user, settings, notifications }; }其他
Array.fromAsync():从异步可迭代对象创建数组
const pages = await Array.fromAsync(fetchPages());Iterator Helpers:惰性求值的链式操作(如.map().filter().take()),大幅提升大数据处理性能
Error.isError():跨 Realm(如 iframe)安全检测 Error 对象
Uint8Array 原生 Base64/Hex 支持:
const base64 = new Uint8Array([72, 101, 108, 108, 111]).toBase64();兼容性与使用建议
- 浏览器支持:Chrome 144+、Firefox 130+ 已支持主要特性 。
- Node.js:需 v20+ 或通过 Babel 转译。
- 新项目:建议直接采用 Temporal、using、Records 等特性。
- 老项目迁移:渐进式替换,优先在新模块使用。