2026 年 JavaScript 开发者需要了解的知识

JavaScript 开发涉及语言特性、运行时、框架、库和工程工具。本文分别介绍这些领域在原文发布时的变化。

语言有哪些新变化

ECMAScript 标准采用年度发布机制。

ECMAScript 2025

ECMAScript 2025 于 2025 年 6 月发布,完整规范已经公开。

迭代器辅助方法

迭代器可以直接使用 .map()、.filter()、.take()、.drop() 等辅助方法,并采用惰性求值。与数组方法的链式调用相比,这种方式可以减少中间数组的创建,并在满足终止条件后停止读取后续元素。

javascript 复制代码
const result = array
  .map(x => x * 2)      // 在内存中创建一个新数组
  .filter(x => x > 10)  // ......又创建一个
  .slice(0, 3);         // ......再创建一个

上述数组方法会依次创建中间结果。对于较大的数组或计算成本较高的操作,这可能增加内存占用和计算量。使用迭代器辅助方法可以改写为:

javascript 复制代码
const result = Iterator.from(array)
  .map(x => x * 2)
  .filter(x => x > 10)
  .take(3)
  .toArray(); // 不创建中间数组;收集到 3 个过滤后的结果即停止,最后生成结果数组

.take(3) 获取的是映射和过滤之后的前 3 个结果,不一定只读取 3 个原始输入元素。.toArray() 会创建最终结果数组,前面的迭代器链不需要逐步创建中间数组。

Iterator.from() 适用于数组、Set、Map、生成器等可迭代对象,使这些数据结构能够使用同一套迭代器辅助方法。

Set 集合方法

Set 是保存唯一值的集合。新增的集合方法支持交集、并集、差集、对称差集,以及子集、超集和不相交关系判断。

javascript 复制代码
const youKnow  = new Set(["JS", "Python", "CSS", "SQL"]);
const jobNeeds  = new Set(["JS", "TypeScript", "Python"]);

// 岗位要求中,你已经掌握的技能
youKnow.intersection(jobNeeds); // → Set {"JS", "Python"}

// 合并全部技能:你掌握的技能 + 岗位要求
youKnow.union(jobNeeds); // → Set {"JS", "Python", "CSS", "SQL", "TypeScript"}

// 岗位要求中,你还没有掌握的技能,也就是技能缺口
jobNeeds.difference(youKnow); // → Set {"TypeScript"}

// 你掌握了,但岗位不要求的技能
youKnow.difference(jobNeeds); // → Set {"CSS", "SQL"}

// 只出现在其中一个集合中,而非两个集合共有的技能
youKnow.symmetricDifference(jobNeeds); // → Set {"CSS", "SQL", "TypeScript"}

// 岗位要求是否全部包含在你掌握的技能中?
jobNeeds.isSubsetOf(youKnow); // → false

// 你是否掌握了全部岗位要求,甚至更多?
youKnow.isSupersetOf(jobNeeds); // → false

// 你掌握的技能与岗位要求是否完全没有交集?
youKnow.isDisjointFrom(jobNeeds); // → false

正则表达式更新

页面内搜索如果将用户输入直接作为正则表达式,输入中的特殊字符可能改变匹配含义。例如,$ 表示结尾断言,不能直接当作普通字符使用。搜索输入应按正则表达式的规则进行转义。

RegExp.escape() 可以将字符串转换为适合在正则表达式中按字面含义匹配的形式。

javascript 复制代码
const query = userInput; // 例如 "$5.00 (off!)"

// ❌ 以前:遇到正则表达式特殊字符,搜索就可能出问题
const badRe  = new RegExp(query, "g");

// ✅ ES2025:一个方法就解决了
const goodRe = new RegExp(RegExp.escape(query), "g");

正则表达式的 i 标志表示不区分大小写。ES2025 的内联修饰符允许在分组中启用或关闭特定标志,从而在同一个表达式中组合区分大小写与不区分大小写的匹配。

javascript 复制代码
// 以前:无法混合区分大小写与不区分大小写的匹配
/[a-z]+@[A-Z]+/i  // i 标志作用于整个表达式

// ES2025:为各个分组设置内联修饰符
/(?i:[a-z.]+)@(?-i:[A-Z]+)\.(?i:com|org)/
// 第一个分组不区分大小写
// 第二个分组区分大小写
// 第三个分组不区分大小写

Promise 更新

Promise.try() 可以把函数调用纳入 Promise 错误处理流程。同步抛出的错误和异步拒绝都可以通过后续的 .catch() 处理。

javascript 复制代码
// 一个可能执行异步操作,也可能同步抛出错误的函数
function loadUser(id) {
  if (!id) throw new Error("No ID");          // 同步抛出错误
  return fetch(`/api/users/${id}`);           // 异步操作
}

// ❌ 以前:两条独立的错误处理路径
let p;
try {
  p = loadUser(id);                           // 在这里捕获同步错误......
} catch (e) { handleError(e); }
p?.catch(e => handleError(e));                // ......在这里捕获异步拒绝

// ✅ ES2025:一次调用,一个 .catch()
Promise.try(() => loadUser(id))
  .then(response => response.json())          // 将 Response 解析为用户数据
  .then(user  => render(user))
  .catch(err  => showError(err));             // 两种错误都能捕获

导入属性

导入属性可以声明模块导入的类型。例如,可以将 JSON 文件直接作为模块导入:

javascript 复制代码
import data from "./file.json" with { type: 'json' }

with 及其后面的对象构成导入属性,用于声明导入类型等信息。

Jake Archibald 在《Importing vs fetching JSON》(导入 JSON 与通过 fetch 获取 JSON)中分析了 JSON 模块导入的限制:静态导入失败会影响整个模块依赖图。动态 import() 可以捕获导入失败:

javascript 复制代码
try {
  const { default: data } = await import(url, {
    with: { type: 'json' },
  });
} catch (error) {
  // 回退逻辑
}

动态导入与 fetch 在响应信息和数据生命周期方面存在差异。模块导入不会像 fetch 那样返回响应对象;导入的数据会保留在页面的模块依赖图中,而通过 fetch 获取的数据在不再被引用后可以被垃圾回收。

导入属性也可用于 CSS 模块脚本:

javascript 复制代码
import componentStyles from "./component.css" with { type: "css" };

CSS 模块脚本允许将样式保存在独立的 CSS 文件中,并通过 adoptedStyleSheets 应用于 Web Component 的 Shadow DOM。CSS 文件可以与对应的 JavaScript 组件放在同一目录中。

javascript 复制代码
import sheet from './styles.css' with { type: 'css' };

class MyComponent extends HTMLElement {
  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.adoptedStyleSheets = [sheet];
  }

  // 其他组件逻辑......
}

ES2025 还包含本文未展开的特性,例如 Float16Array,可在适合的场景中以较低的数值精度换取更低的内存占用。

ECMAScript 2026(预计于 2026 年中发布)

原文发布时,ECMAScript 2026 预计在年中发布。以下是原文列出的已进入 Stage 4、预计纳入该版本的特性。

Temporal API

Temporal API 提供日期、时间、时区和时间跨度的处理能力。此前,相关需求常借助 Moment 等第三方库实现。

原文发布时,Safari 的 Temporal 支持正在开发,并已进入技术预览版。

Temporal 可以直接获取指定时区的当前时间:

javascript 复制代码
const now = Temporal.Now.zonedDateTimeISO("America/New_York");
// 适合程序处理的日期时间表示
console.log(now.toString());

// 或者更便于阅读的表示......
console.log(now.toLocaleString());

TC39 会议资料中的以下示例,可将会议时间转换为当前系统时区的时间:

javascript 复制代码
Temporal.ZonedDateTime.from('2026-03-10T10:00[America/New_York]')
  .withTimeZone(Temporal.Now.timeZoneId()) // 你所在的时区
  .toLocaleString();

Temporal 还提供日历日期运算和时间跨度比较。

使用 Date.setMonth() 为 1 月 31 日增加一个月时,超出 2 月范围的日期会溢出到 3 月:

javascript 复制代码
const date = new Date(2026, 0, 31); // 1 月 31 日
date.setMonth(date.getMonth() + 1); // "加上一个月"
console.log(date.toDateString()); // Tue Mar 03 2026(日期溢出到 3 月)

使用 Temporal 可以得到以下结果:

javascript 复制代码
const jan31 = Temporal.PlainDate.from("2026-01-31");
const feb = jan31.add({ months: 1 });
console.log(feb.toString()); // 2026-02-28 ✅

时间跨度可以通过 Temporal.Duration.compare() 比较:

javascript 复制代码
const a = Temporal.Duration.from({ hours: 25 });
const b = Temporal.Duration.from({ days: 1 });

const cmp = Temporal.Duration.compare(a, b, { relativeTo: Temporal.Now.plainDateISO() });
console.log(cmp); // 1(25 小时 > 1 天)✅

显式资源管理

显式资源管理通过 using 和 await using 声明需要释放的资源。using 用于同步释放,离开作用域时调用 [Symbol.dispose]();await using 用于异步释放,离开作用域时调用并等待 [Symbol.asyncDispose]()。

javascript 复制代码
class FileHandle {
  constructor(path) {
    this.path = path;
    console.log(`Opened ${path}`);
  }

  async write(data) {
    // ......写入数据
  }

  async [Symbol.asyncDispose]() {
    await someFlushOperation();
    console.log(`Flushed and closed ${this.path}`);
  }
}

async function saveData() {
  await using file = new FileHandle("output.txt");
  await file.write("hello world");
  // 文件会在这里自动刷新并关闭,即使抛出了错误
}

DisposableStack 和 AsyncDisposableStack 可以登记多个资源或清理回调,在释放时按登记的相反顺序执行清理。

javascript 复制代码
async function runJob() {
  await using stack = new AsyncDisposableStack();

  const db = stack.use(await openDatabase());
  const file = stack.use(new FileHandle("output.txt"));
  const tmpDir = stack.defer(async () => removeTempDir("/tmp/job"));

  // 执行工作......
  await file.write(await db.query("SELECT * FROM jobs"));

  // 这三项清理会在这里按相反顺序执行,即使过程中抛出了错误
}

Array.fromAsync 与迭代器串接

原文提到,Array.fromAsync 在 2024 年已有实现,并预计纳入 ES2026。它会遍历异步迭代器,等待每个产出的值,并将结果收集为一个普通数组。

javascript 复制代码
async function* fetchNumbers() {
  yield 1;
  await new Promise(r => setTimeout(r, 100)); // 模拟异步延迟
  yield 2;
  await new Promise(r => setTimeout(r, 100));
  yield 3;
}

const numbers = await Array.fromAsync(fetchNumbers());
console.log(numbers); // [1, 2, 3]

Array.fromAsync 可用于收集分页等异步操作产生的结果,也可以接收 Promise 数组并等待各个值。

Iterator.concat 可以按顺序串接多个迭代器,以惰性方式遍历其中的元素,而不必先将它们展开到一个数组中。提前退出迭代时,不需要继续收集后续元素。

javascript 复制代码
const page1 = [{ id: 1 }, { id: 2 }][Symbol.iterator]();
const page2 = [{ id: 3 }, { id: 4 }][Symbol.iterator]();
const page3 = [{ id: 5 }, { id: 6 }][Symbol.iterator]();

for (const item of Iterator.concat(page1, page2, page3)) {
  process(item); // 以惰性方式逐项遍历所有分页
}

Error.isError()

Error.isError() 用于判断一个值是否为真正的 Error 对象。

集中式错误上报可能接收来自 Web Worker 或 iframe 等不同执行域(realm)的错误对象,需要能够跨执行域判断错误类型。

Math.sumPrecise

浮点数运算 0.1 + 0.2 的结果为 0.30000000000000004。

原文的示例中,Math.sumPrecise([0.1, 0.2]) 得到相同结果。因此,这个方法并不会把该表达式的结果变为精确的十进制 0.3。

Base64 与十六进制编码

字节数组可以通过 .toBase64() 和 .toHex() 转换为 Base64 或十六进制字符串。

javascript 复制代码
const val = "Frontend Masters!";
const textEnc = new TextEncoder();
const bytes = textEnc.encode(val);
console.log(bytes.toBase64());
// 'RnJvbnRlbmQgTWFzdGVycyE='
console.log(bytes.toHex());
// '46726f6e74656e64204d61737465727321'

框架有哪些新变化

React 生态

React 19 于 2024 年 12 月发布,原文发布时的版本为 19.2。

原文介绍了 React 生态中的 RSC(React Server Components,React 服务端组件)、React Compiler 和 Server Actions:

  • RSC:服务端组件在服务器上执行,相应的组件实现不需要作为客户端 JavaScript 发送,客户端接收渲染所需的数据。
  • Server Actions:用于调用在服务器上执行的函数,表单处理是其中一种应用场景。
  • React Compiler:通过编译阶段的分析完成部分性能优化,减少手动编写记忆化优化的需求。

原文发布时,React Native 已发布 0.83。

原文指出,2025 年 React 服务端相关技术曾接连出现严重安全漏洞。

Vue 生态

原文发布时,Vue 3.5 为稳定版本,Vue 3.6 已进入 alpha 阶段,包含可选择启用的 Vapor Mode。原文引用的性能目标是与 Solid 和 Svelte 5 相当。

尤雨溪创立的 VoidZero 推出 Vite+,覆盖 Vite、格式化、代码检查和测试等工具。

这些工具并非 Vue 专属,也可用于其他 JavaScript 项目。

原文发布时,Nuxt 已发布 4.0。Nuxt 的维护团队 NuxtLabs 被 Vercel 收购。

Vue 状态管理库 Pinia 已发布 v3,并移除了 Vue 2 支持。

Svelte 生态

Svelte 5 引入 Runes API,调整了响应式机制,采用更细粒度的响应式处理。

JavaScript 运行时

JavaScript 运行时包括浏览器内置运行时,以及可以独立运行程序的 Node.js、Bun、Deno 等。

Node.js、Bun 和 Deno 都增加了 TypeScript 运行支持;Bun 和 Deno 也持续扩展与 Node.js 生态的兼容能力。

Node.js

Node.js 可以直接运行支持的 TypeScript 文件,例如:

bash 复制代码
node my-script.ts

从 Node 22.18.0 开始,运行支持的 TypeScript 文件不再需要 --experimental-strip-types 标志。这种运行方式会移除类型信息,不执行 TypeScript 类型检查。

Node.js 的更新还涉及安全性、性能和浏览器 JavaScript API 的兼容。

Node.js 提供内置测试运行器,可以减少对外部测试工具的依赖;权限模型用于限制程序对系统资源的访问。

Bun

Bun 1.3 增加了开发服务器相关功能。将 bun 指向 HTML 文件,可以启动开发服务器:

bash 复制代码
bun './**/*.html'

该方式包含文件处理和打包能力。

Anthropic 于 2025 年年底收购 Bun。

Deno

Deno 2 支持 Node.js 兼容能力,也可以通过 npm: 指定方式使用 npm 包。

Deno 默认限制程序访问敏感资源。其官方文档说明:

Deno 默认是安全的。除非你明确启用权限,否则通过 Deno 运行的程序无法访问敏感 API,例如文件系统、网络连接或环境信息。你必须通过命令行标志或运行时权限提示,明确授予对这些资源的访问权限。这是它与 Node 的一个主要区别:在 Node 中,依赖会自动获得对所有系统 I/O 的完整访问权限,可能给项目引入隐藏的安全漏洞。

构建工具

Vite

Vite 起源于 Vue 生态,也支持其他前端框架和项目。

Vite 本地开发时按需处理发生变化的模块,生产构建时执行打包。

原文发布时,Vite 已发布 v8,打包工具由 Rollup 切换为 Rolldown。统一工具链可以在不同工具之间共享解析器等基础能力。

Vite+ 覆盖开发服务器、格式化、代码检查、类型检查、测试、任务运行、monorepo 支持和打包。

VoidZero 还在开发名为 Void 的部署平台,使用 Cloudflare 的托管、数据存储和云函数等服务。

原文列出的平台能力包括数据库、KV 存储、对象存储、AI 推理、身份验证、队列和定时任务。

Astro、SolidStart、SvelteKit 和 Nuxt 等框架使用 Vite。Next.js 使用 webpack 和 Turbopack。原文还提到 Cloudflare 借助 AI 进行的 Next.js 到 Vite 的移植项目。

Turbopack

Turbopack 是 Vercel 开发、基于 Rust 的打包工具,从 Next.js v16 开始成为默认打包工具。原文引用的刷新速度提升为此前 webpack 方案的 5~10 倍;具体表现取决于项目和测试场景。

webpack

webpack 的 2026 年开发计划包含减少对部分 loader 的依赖,以及简化配置等改进。

TypeScript

原文发布时,TypeScript 已发布 v6,v7 预计于 2026 年中推出,并计划切换到基于 Go 的编译器。v6 包含为编译器迁移做准备的配置调整。Bytes 简报将这些调整概括为:

严格模式现在默认是 true,module 默认是 esnext,target 会跟随当年的 ES 规范,目前为 es2025。types 现在默认是一个空数组,不再自动把 node_modules/@types 中的所有类型都纳入。仅最后这一项,就可能导致很多项目无法正常工作,不过也应该能让它们提速 20%~50%。

原文提到,新的编译器在 VS Code 和 Playwright 等使用场景中展示了约 10 倍的速度提升;这属于原文引用的性能结果。

原文引用的 GitHub 统计显示,TypeScript 在相关语言统计中排名第一,同比增长 66%。

在 JavaScript 中直接加入类型?

JavaScript 类型注释提案探索在语言中直接加入类型语法。原文发布时,该提案尚未提供可替代 TypeScript 完整能力的方案。

AI

AI 编程工具可用于生成 JavaScript 和 TypeScript 代码。生成的代码仍需进行审查、类型检查和测试。

测试

JavaScript 测试工具包括 Jest、Jasmine、Mocha 和 Vitest 等。

Vitest 兼容 Jest 的测试 API,可以支持现有测试的迁移。

Vitest 的浏览器模式可以在真实浏览器中运行测试,并可配合 Playwright 进行组件测试。Playwright 本身也支持端到端测试。

元框架

Next.js

Next.js v16 是首个默认使用 Turbopack 的版本,同时改进了日志和错误信息。

原文介绍了 Next.js 对 React Compiler 和 React Server Components 的集成。性能收益需要结合具体应用场景评估。

Next.js 提供 MCP 服务器,可以向接入的 AI 开发工具提供项目相关信息。

原文还提到 React 19 相关的 <ViewTransition> 支持。

Remix / React Router

Remix 被 Shopify 收购后发布了 v2。原计划作为 Remix v3 发布的内容,随后整合为 React Router v7。

原文发布时,新的 Remix v3 正在开发,计划使用独立组件模型,不再以 React 为组成部分。

Remix Jam 活动介绍了相关开发方向。

TanStack

TanStack 是一组工具的集合,包含 TanStack Router 等。其路由能力进一步扩展为框架 TanStack Start。

Astro

Cloudflare 于 2026 年收购 Astro。原文还提到基于 Astro 构建的 WordPress 类项目。

Astro 采用默认静态的页面模式,支持现代 JavaScript 框架的组件化架构,并允许按需加入动态行为。

原文介绍了 Astro 6.0 的开发运行时自定义、内容安全策略和实验性编译器等功能,以及随后 6.1 版本的配置改进。

npm

微软/GitHub 于 2020 年收购 npm。

npm 生态在 2025 年发生了多起供应链安全事件。s1ngularity 事件涉及凭证、令牌和配置文件窃取,并将这些信息公开发布到 GitHub。

接着是 debug/chalk 事件:恶意的软件包更新被发布出去,能够把加密货币交易重定向到攻击者的钱包。

Shai-Hulud 蠕虫事件涉及自我复制和凭证窃取。原文称,其 2.0 版本包含覆盖或删除用户主目录文件的行为,事件波及 796 个 npm 包,相关包的下载量超过 2000 万次。

Socket 等工具用于检测依赖包中的风险行为。

工程基础能力

语言基础、异步机制、模块系统和运行时行为,是理解框架与工程工具的基础。

AI 辅助生成代码的开发流程仍包含需求分析、架构设计、代码审查和测试验证。

原文链接:

Master.dev Blog

相关推荐
_馒头1 小时前
pixiJs游戏开发实践 - 跳棋小游戏
javascript·vue.js
用户11481867894841 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界1 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
Bazingga1 小时前
RAG评测体系保姆级教程:生产级实践指南
后端
葡萄城技术团队1 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一2 小时前
优化修整算法
前端·javascript·算法
楠楠子呀2 小时前
英语、西语、阿语客户各开一个口:多语言获客的分流方案
开发语言·javascript·ecmascript·跨境电商·whatsapp·营销工具
tachibana23 小时前
使用for range 的时候,它的地址会发生变化吗?
开发语言·后端·golang·go·语法
蜗牛互联网3 小时前
GPT-6 与 Intelligent UI:从回答到可审计操作的产品迁移
java·人工智能·后端