javascript
ES2021~ES2025 新特性
By AI-Writer 20 min read
ECMAScript 每年发布一个新版本,持续为 JavaScript 注入新能力。本文系统梳理 ES2021 到 ES2025 的关键特性,帮助你跟上语言演进的步伐。
ES2021(ES12)
1. 逻辑赋值运算符
将逻辑运算与赋值合二为一:
javascript
let a = 1;
let b = 0;
// 逻辑与赋值:a &&= b 等价于 a = a && b
a &&= b; // a 保持 1(因为 1 && 0 为 0,但 a 为真值才执行)
// 逻辑或赋值:仅当左侧为 falsy 时才赋值
let config = null;
config ||= { theme: 'dark' };
console.log(config); // { theme: 'dark' }
// 逻辑空赋值:仅当左侧为 null 或 undefined 时才赋值
let count = 0;
count ??= 10;
console.log(count); // 0 —— 0 不是 nullish,所以不赋值
let missing;
missing ??= 20;
console.log(missing); // 20| 运算符 | 等价写法 | 赋值条件 |
|---|---|---|
a &&= b | a = a && b | a 为 truthy |
a ||= b | a = a || b | a 为 falsy |
a ??= b | a = a ?? b | a 为 nullish |
2. Promise.any
返回最先 fulfilled 的 Promise,全部 rejected 则抛 AggregateError:
javascript
const promises = [
fetch('https://slow.example.com'),
fetch('https://fast.example.com'),
fetch('https://backup.example.com')
];
try {
const response = await Promise.any(promises);
console.log('最快的响应:', response.url);
} catch (error) {
console.error('全部失败:', error.errors);
}3. 数值分隔符
用下划线 _ 分隔大数字,提升可读性:
javascript
const billion = 1_000_000_000;
const bytes = 0xFF_FF_FF_FF; // 十六进制
const binary = 0b1010_0001; // 二进制
const float = 1_234.567_890; // 小数4. String.prototype.replaceAll
替换字符串中所有匹配项:
javascript
const str = 'foo bar foo baz foo';
// 以前需要正则表达式 /g 标志
str.replace(/foo/g, 'qux');
// ES2021 新增
str.replaceAll('foo', 'qux'); // "qux bar qux baz qux"ES2022(ES13)
1. 类私有字段与方法
使用 # 前缀声明真正的私有成员:
javascript
class Counter {
#count = 0; // 私有字段
increment() {
this.#count++;
}
get #formatted() { // 私有 getter
return `Count: ${this.#count}`;
}
#log() { // 私有方法
console.log(this.#formatted);
}
print() {
this.#log();
}
}
const c = new Counter();
c.increment();
c.print(); // "Count: 1"
// c.#count; // SyntaxError!2. 类静态块
在类定义时执行一次性初始化逻辑:
javascript
class Database {
static #connectionString;
static #poolSize;
static {
// 静态块 —— 类初始化时执行一次
this.#connectionString = process.env.DB_URL;
this.#poolSize = parseInt(process.env.DB_POOL) || 10;
}
static connect() {
return `Connecting to ${this.#connectionString} (pool: ${this.#poolSize})`;
}
}3. at() 方法
支持负索引,从末尾访问数组/字符串元素:
javascript
const arr = [10, 20, 30, 40, 50];
// 传统方式获取最后一个元素
arr[arr.length - 1]; // 50
// ES2022
arr.at(-1); // 50
arr.at(-2); // 40
arr.at(0); // 10
// 字符串同样支持
'hello'.at(-1); // 'o'4. Object.hasOwn
替代 Object.prototype.hasOwnProperty.call:
javascript
const obj = { foo: 1 };
// 旧写法
Object.prototype.hasOwnProperty.call(obj, 'foo');
// ES2022
Object.hasOwn(obj, 'foo'); // true
Object.hasOwn(obj, 'toString'); // false(继承属性)5. Error Cause
传递错误链上下文:
javascript
try {
await fetchUser();
} catch (err) {
throw new Error('加载用户数据失败', { cause: err });
}
// 后续捕获
} catch (err) {
console.error(err.message); // "加载用户数据失败"
console.error(err.cause.message); // 原始错误信息
}ES2023(ES14)
1. Array.findLast / findLastIndex
从数组末尾开始查找:
javascript
const nums = [5, 12, 8, 130, 44, 8];
// 从前向后找第一个
nums.find(n => n > 10); // 12
nums.findIndex(n => n > 10); // 1
// 从后向前找第一个(ES2023)
nums.findLast(n => n > 10); // 44
nums.findLastIndex(n => n > 10); // 42. Array.toSorted / toReversed / toSpliced / with
返回新数组的非变异方法:
javascript
const arr = [3, 1, 4, 1, 5];
// 以前会改变原数组
arr.sort(); // 变异!
arr.reverse(); // 变异!
// ES2023 返回新数组
const sorted = arr.toSorted(); // [1, 1, 3, 4, 5]
const reversed = arr.toReversed(); // [5, 1, 4, 1, 3]
const spliced = arr.toSpliced(1, 2, 'a', 'b'); // [3, 'a', 'b', 1, 5]
const replaced = arr.with(2, 99); // [3, 1, 99, 1, 5]
// 原数组保持不变
console.log(arr); // [3, 1, 4, 1, 5]这组方法是函数式编程风格的重要补充。
ES2024(ES15)
1. Array.groupBy / Object.groupBy
按条件分组(后调整为静态方法 Object.groupBy):
javascript
const products = [
{ name: 'Apple', category: 'fruit' },
{ name: 'Carrot', category: 'vegetable' },
{ name: 'Banana', category: 'fruit' }
];
const grouped = Object.groupBy(products, p => p.category);
console.log(grouped);
// {
// fruit: [
// { name: 'Apple', category: 'fruit' },
// { name: 'Banana', category: 'fruit' }
// ],
// vegetable: [
// { name: 'Carrot', category: 'vegetable' }
// ]
// }2. Map.prototype.emplace
Map 的便捷更新方法(提案阶段可能有调整,以最终规范为准):
3. Promise.withResolvers
创建带有外部 resolve/reject 方法的 Promise:
javascript
// ES2024
const { promise, resolve, reject } = Promise.withResolvers();
// 以前需要这样写:
// let resolve, reject;
// const promise = new Promise((res, rej) => { resolve = res; reject = rej; });
// 实用场景:在事件回调外部 resolve
document.getElementById('btn').addEventListener('click', () => {
resolve('clicked');
});
const result = await promise;4. String.prototype.isWellFormed / toWellFormed
检查/修复 Unicode 代理对:
javascript
const bad = 'abc\uD800'; // 未配对的代理项
bad.isWellFormed(); // false
bad.toWellFormed(); // "abc�"(替换为替换字符)ES2025(ES16)预览
以下特性处于标准化晚期或已确定纳入:
1. using 声明(显式资源管理)
自动管理需要清理的资源:
javascript
// 类似 Python 的 with 语句
{
using file = await openFile('data.txt');
// 块结束时自动调用 file[Symbol.dispose]()
const content = await file.read();
}
// file 已自动关闭
// 异步资源
{
await using conn = await db.connect();
const rows = await conn.query('SELECT * FROM users');
}
// conn 已自动释放2. 正则表达式 /v 标志
更强大的 Unicode 集合操作:
javascript
// /v 标志支持集合运算
const re = /[\p{Letter}&&[^\p{ASCII}]]/v; // 非 ASCII 字母3. Array.fromAsync
从异步可迭代对象创建数组:
javascript
const asyncIterator = {
async *[Symbol.asyncIterator]() {
yield 1;
yield 2;
yield 3;
}
};
const arr = await Array.fromAsync(asyncIterator);
console.log(arr); // [1, 2, 3]新特性速查表
| 版本 | 特性 | 用途 |
|---|---|---|
| ES2021 | &&= ||= ??= | 逻辑赋值 |
| ES2021 | Promise.any | 竞速取首个成功 |
| ES2021 | 数值分隔符 | 提升大数字可读性 |
| ES2021 | replaceAll | 全局字符串替换 |
| ES2022 | #private | 类私有成员 |
| ES2022 | 静态块 | 类级初始化逻辑 |
| ES2022 | at(-n) | 负索引访问 |
| ES2022 | Object.hasOwn | 安全属性检查 |
| ES2022 | Error.cause | 错误链 |
| ES2023 | findLast / findLastIndex | 反向查找 |
| ES2023 | toSorted / toReversed / with | 非变异数组方法 |
| ES2024 | Object.groupBy | 数组分组 |
| ES2024 | Promise.withResolvers | 外部 resolve |
| ES2025 | using 声明 | 资源自动管理 |
| ES2025 | Array.fromAsync | 异步转数组 |
使用建议
Babel 转译配置
json
// .babelrc
{
"presets": [
["@babel/preset-env", {
"targets": "> 0.25%, not dead"
}]
]
}TypeScript 配置
json
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2023", "DOM"]
}
}现代浏览器对新特性的支持越来越及时,Node.js LTS 版本也快速跟进。对于学习而言,尽早了解并使用这些新特性能让代码更简洁、表达力更强。
#javascript
#es2021
#es2022
#es2023
#es2024
#es2025
#新特性
评论
A
Written by
AI-Writer
Related Articles
javascript
#14 手写二叉搜索树:插入、查找、删除与遍历全解析
从零实现二叉搜索树(BST),深入掌握插入、查找、删除、四种遍历算法的递归与非递归实现,并了解 AVL 树与红黑树的平衡思想。
Read More javascript
#7 Promise 与 async/await
深入理解 JavaScript 异步编程核心——Promise 状态机、组合 API 与 async/await 语法糖,掌握错误处理与事件循环的协作关系。
Read More