【js】ES2025新语法糖
前言
作为前端开发者,了解JavaScript最新动态至关重要。
ES2025(ECMAScript 2025)是 ECMAScript 语言标准的第 16 版,于 2025 年 6 月正式定稿。它引入了一些备受期待的、能显著提升开发者体验和语言能力的新特性——叹为观止!
不可变数据 Records & Tuples
对标数组和对象,提供真正的——不可变数据结构
特性:
深度不可变:创建后内容及其嵌套内容都不能改变。
// Record(记录):const userRecord = #{ id: 1, name: \"张三\", email: \"zs@cc.com\"};// Tuple(原组):const coordinates = #[10, 20, 30];
按值比较: 两个具有相同结构和内容的 Record 或 Tuple 严格相等。
// 严格相等检查const user1 = #{ id: 1, name: \"张三\" };const user2 = #{ id: 1, name: \"张三\" };console.log(user1 === user2); // true!
用途: 状态管理(Redux 等)、安全地共享数据、作为 Map/Set 的键(因为按值比较)、确保数据不被意外修改。
// 嵌套结构const complexData = #{users: #[ #{ id: 1, name: \"张三\" }, #{ id: 2, name: \"李四\" } ],config: #{ theme: \"dark\", language: \"zh-CN\" }};
原始数据类型 Decimal
原始数据类型 decimal,用于精确的十进制浮点数运算,解决Number型精度问题。
// 传统写法:精度丢失
console.log(0.1 + 0.2); // 0.30000000000000004// 新写法:精确计算
console.log(0.1m + 0.2m); // 0.3m
// 与Number互转const decimalValue = 123.456m;const numberValue = Number(decimalValue); // 123.456const backToDecimal = Decimal(numberValue); // 123.456m// 财务计算const price = 19.99m;const tax = 0.08m;const total = price * (1m + tax);console.log(total); // 21.5892m
管道函数链 Pipeline Operator
提供一种更可读的方式来对值应用一系列函数转换(函数调用)。用于深层嵌套函数调用。
value |> func(%) 或 value |> func(%, arg)
% 是一个占位符,代表管道左侧的值。
// 没有管道const result = exclaim(capitalize(doubleSay(\"hello\")));// 使用管道const result = \"hello\" |> doubleSay(%) // \"hellohello\" |> capitalize(%) // \"Hellohello\" |> exclaim(%); // \"Hellohello!\"// 完整的用户数据处理流程constprocessUsers = (users) => users |> (% => %.filter(user => user.active)) |> (% => %.map(user => ({ ...user, displayName: `${user.firstName} ${user.lastName}` }))) |> (% => %.sort((a, b) => a.displayName.localeCompare(b.displayName))) |> (% => %.slice(0, 10));// 异步管道处理constfetchAndProcessData = async (url) => url |> fetch(%) |> await %.json() |> processUsers(%) |> (% => ({ data: %, timestamp: Date.now() }));
错误处理 throw Expressions
允许在任何期望表达式的地方使用 throw, 简化在表达式上下文中抛出错误的写法,避免不必要的函数包装或语句块。
throw new Error() 可以作为表达式使用。
// 1. 三元表达式/条件运算符function getEnv(env) { return env ?? throw new Error(\"Environment variable not set\");}// 2. 箭头函数默认值 (之前只能用语句块)const fn = (param = throw new Error(\"param required!\")) => { ... };// 3. 逻辑运算符const value = maybeValue || throw new Error(\"No value\");// 4. 在解构中使用const { prop } = obj ?? throw new Error(\"obj is null/undefined\");
// 新的try表达式const result = tryfetchData() catch (error) {console.error(\'获取数据失败:\', error);return { error: error.message };};// 链式错误处理constprocessData = (data) =>tryparseJSON(data) .then(validateSchema) .then(transformData) .catch(ParseError, (e) => { return { error: \'数据格式无效\', details: e.message }; }) .catch(ValidationError, (e) => { return { error: \'数据验证失败\', details: e.message }; }) .catch((error) => { return { error: \'处理失败\', details: error.message }; });// 错误传播操作符constsafeOperation = (input) => {const parsed = parseInput(input)?; // 如果失败,直接返回错误const validated = validateInput(parsed)?;const result = processInput(validated)?;return { success: true, data: result };};
导入的断言 import with
// 导入JSON模块import config from\'./config.json\'with { type: \'json\' };// 导入CSS模块import styles from\'./styles.css\'with { type: \'css\' };// 导入WebAssembly模块import wasmModule from\'./math.wasm\'with { type: \'webassembly\' };// 带断言的动态导入constloadConfig = async (env) => {const config = awaitimport(`./config-${env}.json`, { with: { type: \'json\' } });return config.default;};// 条件导入if (process.env.NODE_ENV === \'development\') {import devConfig from\'./config-dev.json\'with { type: \'json\' };}
迭代器
链式方法,数据处理更加流畅:
function* fibonacci() {let a = 0, b = 1;while (true) { yield a; [a, b] = [b, a + b]; }}const result = fibonacci() .take(20) // 取前20项 .filter(n => n % 2 === 0) // 只保留偶数 .map(n => n * n) // 平方 .take(5) // 取前5个 .toArray(); // 转为数组console.log(result); // [0, 4, 64, 1024, 7744]
// 支持异步生成器asyncfunction* fetchPages(baseUrl) {let page = 1;while (true) { const response = awaitfetch(`${baseUrl}?page=${page}`); const data = await response.json(); if (data.items.length === 0) break; yield* data.items; page++; }}const allItems = awaitfetchPages(\'/api/items\') .filter(item => item.active) .map(item => ({ ...item, processed: true })) .take(100) .toArray();
Temporal API
日期时间处理,不再需要借助第三方
// 简化的日期创建const now = Temporal.now();const birthday = @2024-01-15; // 新的日期字面量语法const meeting = @2024-12-25T10:30:00[Asia/Shanghai];// 日期时间运算的语法糖const nextWeek = now + 7.days;const lastMonth = now - 1.month;const deadline = meeting + 2.hours + 30.minutes;// 时间范围语法const workingHours = @09:00..17:00;const workingDays = @Monday..Friday;console.log(workingHours.contains(@14:30)); // trueconsole.log(workingDays.contains(Temporal.now().dayOfWeek)); // 检查今天是否是工作日
字符串模版增强
// 自动处理多行缩进const html = html` ${title}
${content}
`; // 自动处理缩进// 自定义插值处理const sql = sql`SELECT * FROM usersWHERE age > ${minAge}AND city = ${city}`; // 自动防止SQL注入// 国际化模板const message = i18n`你好 ${name},你有 ${count} 条新消息`; // 自动处理语言环境和复数规则// 样式化字符串const styledText = css`color: ${primaryColor};font-size: ${fontSize}px;margin: ${margin};`;
进化的解构赋值
// 对象模式解构const user = { id: 1, profile: { name: \"张三\", age: 25 } };// 带默认值的深度解构const { id, profile: { name, age = 18 } = {} } = user;// 条件解构const { id if id > 0, name iftypeof name === \'string\' } = user;// 数组模式解构const numbers = [1, 2, 3, 4, 5];const [first, second, ...rest where rest.length > 2] = numbers;// 函数参数模式解构functionprocessUser({ id, name if name.length > 0, age = 18 if age >= 0, ...extra}) {// 只解构符合条件的参数return { id, name, age, extra };}
总结
ES2025 是一次重要的更新,带来了:
强大的不可变数据结构: Records & Tuples,提升状态管理安全性和性能。
精确数值计算: Decimal 类型,解决金融等地方的精度痛点。
标准化元编程: Decorators 最终定稿,为框架和库提供统一基础。
更优雅的函数链: Pipeline Operator (|>
),提升数据处理代码可读性。
更简洁的错误抛出: throw
Expressions,使错误处理在表达式上下文中更直接。
现代化的日期时间处理:Temporal API新增了语法糖,使用更加便捷。
升级的导入断言:import from with 更安全的模块导入
这些特性极大地增强了 JavaScript 在数据操作、精确计算、元编程、代码可读性和错误处理方面的能力,标志着语言持续向前发展以满足现代开发需求。随着浏览器和 JavaScript 引擎 (V8, SpiderMonkey, JavaScriptCore) 以及 Babel/TypeScript 等工具逐步实现这些特性,开发者将能够更广泛地应用它们。