
在 TC39(ECMAScript 标准制定委员会)以及 Deno 团队等活跃贡献者的推动下,JavaScript 正持续快速演进。在最近召开的第 108 次 TC39 会议上,共有 9 项提案完成了阶段推进------涵盖从早期概念(0 阶段)到完全标准化特性(4 阶段)的全流程。
下文将概述即将落地的特性、仍处于实验阶段的功能,以及这些变化可能对 JavaScript 编码方式产生的影响。
阶段四(Stage 4):可投入使用
该阶段的特性已完全标准化,可直接在生产环境中使用。
显式资源管理(using 关键字)
JavaScript 终于通过新的 using 关键字(及其异步变体 await using)实现了确定性资源清理。这一特性借鉴了 C# 和 Python 的设计思路,能确保文件、网络套接字等资源在退出代码块时被正确释放。
对象可通过实现 Symbol.dispose 或 Symbol.asyncDispose 方法,让资源清理操作自动执行。
JavaScript
class FileHandle {
constructor(name) {
this.name = name; // 执行文件打开操作...
}
// 资源释放逻辑,会自动调用
[Symbol.dispose]() {
console.log(`${this.name} closed`);
}
}
function readFile() {
{
// 声明资源,代码块结束后自动释放
using file = new FileHandle("data.txt");
// 执行文件操作...
}
// 此处会自动调用 file.[Symbol.dispose]()
}
✅ 当前支持情况:Chrome 134、Firefox 134、Deno v2.3 已支持。
在 Deno 环境中,该特性可用于 Deno.File、Deno.Conn 等资源管理,示例如下:
JavaScript
// 声明服务器资源,代码执行完自动停止服务
using server = Deno.serve({ port: 8000 }, () => {
return new Response("Hello, world!");
});
const response = await fetch("http://localhost:8000");
console.log(await response.text()); // 输出 "Hello, world!"
// 服务器在此处自动停止
此外,Deno 团队还提议扩展 using 的功能,以简化异步上下文传播(如追踪、日志记录、调用链追踪等场景)。
Array.fromAsync 方法
与 Array.from 功能类似,但支持异步可迭代对象(async iterables),并返回一个最终会解析为数组的 Promise。
JavaScript
// 定义异步生成器
async function* generate() {
yield await Promise.resolve(1);
yield await Promise.resolve(2);
}
// 从异步生成器中创建数组
const nums = await Array.fromAsync(generate());
console.log(nums); // 输出 [1, 2]
✅ 当前支持情况:所有主流浏览器、Deno v1.38、Node.js v22 已支持。
Error.isError 方法
提供了一种跨上下文/跨继承链检测错误的可靠方式,解决了传统 instanceof Error 检测不准确的问题。
JavaScript
Error.isError(new TypeError("oops")); // 输出 true(正确识别 Error 实例)
Error.isError({ name: "TypeError", message: "oops" }); // 输出 false(排除普通对象)
✅ 当前支持情况:所有主流浏览器、Deno v2.2 已支持。
阶段三(Stage 3):候选特性
该阶段特性已完成设计,正在等待浏览器和运行时的实现,短期内可投入使用。
不可变 ArrayBuffer(Immutable ArrayBuffer)
新增 transferToImmutable() 和 sliceToImmutable() 方法,用于创建安全的不可变二进制数据,避免数据被意外修改。
JavaScript
// 创建一个长度为 100 的 ArrayBuffer
let buf = new ArrayBuffer(100);
// 将原有缓冲区的所有权转移到不可变对象中
let imm = buf.transferToImmutable();
console.log(buf.byteLength, imm.byteLength); // 输出 0, 100(原缓冲区已清空)
imm[0] = 1; // ❌ 报错:TypeError(不可变对象无法修改)
核心用途:适用于多线程、Worker 线程场景,以及 Deno.writeFile() 等二进制 API,可避免不必要的数据拷贝,提升性能。
阶段二(Stage 2):草案阶段
该阶段特性已确定基本语法和行为,但细节仍可能调整,暂不建议生产使用。
Random.Seeded(带种子的随机数)
支持确定性随机数生成,可通过固定种子获得可重复的随机序列。
JavaScript
// 以 42 为种子创建随机数生成器
const prng = new Random.Seeded(42);
console.log(prng.random()); // 每次运行都会生成相同的序列
核心用途:适合模拟实验、游戏开发、测试用例等需要稳定随机结果的场景。
Number.prototype.clamp(数字范围限制方法)
作为 Math.min(Math.max(x, min), max) 的简洁替代方案,可快速将数字限制在指定范围内。
JavaScript
(5).clamp(0, 10); // 输出 5(数字在范围内,保持不变)
(-5).clamp(0, 10); // 输出 0(数字小于最小值,取最小值)
(15).clamp(0, 10); // 输出 10(数字大于最大值,取最大值)
阶段一(Stage 1):早期提案
该阶段仅为初步想法,语法和功能可能发生重大变化,主要用于收集社区反馈。
Intl.NumberFormat 中的末尾零显示(Trailing Zeros)
新增 trailingZeroDisplay 配置项,让数字格式化更简洁,可灵活控制小数部分末尾零的显示方式。
JavaScript
// 最小保留 2 位小数,末尾零正常显示
new Intl.NumberFormat("en", {
minimumFractionDigits: 2,
trailingZeroDisplay: "auto"
}).format(1.5); // 输出 "1.50"
// 若为整数,自动去除末尾零(仅显示整数部分)
new Intl.NumberFormat("en", {
trailingZeroDisplay: "stripIfInteger"
}).format(2); // 输出 "2"
比较功能(Comparisons)
旨在提供一种标准化的数值差异输出方式,可生成类似 diff 工具的对比结果,适用于测试框架断言、日志打印等场景。
随机数命名空间(Random Namespace)
提供便捷的随机数工具方法,支持生成指定范围的数字、从数组中抽样、打乱数组等操作。
JavaScript
Random.int(-5, 5); // 输出 -1(生成 -5 到 5 之间的随机整数)
Random.sample(["A", "B"]); // 输出 "B"(从数组中随机抽取一项)
Random.shuffle([1,2,3]); // 输出 [3,1,2](随机打乱数组顺序)
未来展望
JavaScript 的演进步伐丝毫没有放缓。TC39 正围绕现代开发需求塑造语言特性,重点覆盖:异步工作流优化、更安全的数据处理、结果可复现性提升,以及开发者体验改善。
Deno 团队始终是这些特性的积极推动者,会尽早将其集成到运行时中,以验证实际应用价值。下一次 TC39 会议定于 9 月底召开,届时将继续推进上述提案的讨论。
🔗 参考来源:
- Deno 官方博客
- TC39 提案库
- ECMAScript 草案文档