从 ES2016(ES7)开始,ECMAScript 每年发布一个版本,每次更新都聚焦于实用的小特性迭代。以下是 2016 年至今的主要版本及重大改进:
ES2016(ES7)- 2016 年
- Array.prototype.includes
判断数组是否包含某个元素,替代 indexOf(更直观,支持 NaN 判断):
[1, 2, NaN].includes(NaN); // true(indexOf 会返回 -1)
- 指数运算符( ****** )
简化幂运算,替代 Math.pow:
2 **3; // 8(等价于 Math.pow(2, 3))
###** ES2017(ES8)- 2017 年 **-Object.values() / Object.entries()
快速获取对象的值数组和键值对数组:
const obj = { a: 1, b: 2 };
Object.values(obj); // [1, 2]
Object.entries(obj); // [['a', 1], ['b', 2]]
-String.prototype.padStart() / padEnd() 字符串补全(常用于格式化,如时间补零):
'5'.padStart(2, '0'); // "05"
'abc'.padEnd(5, '-'); // "abc--"
-** 异步函数(async/await)** 简化 Promise 链式调用,用同步写法实现异步逻辑:
async function fetchData() {
const res = await fetch('url'); // 替代 .then() 链式
const data = await res.json();
return data;
}
-** 共享内存与原子操作(SharedArrayBuffer / Atomics)** 支持多线程共享内存(主要用于 Web Worker 高性能计算)。
###** ES2018(ES9)- 2018 年 - 异步迭代(for-await-of)** 遍历异步数据源(如异步生成器):
async function process() {
for await (const data of asyncGenerator()) {
console.log(data);
}
}
-** 对象展开 / 剩余属性(...)** 扩展对象的复制与合并:
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // 合并对象
const { a, ...rest } = obj2; // 剩余属性:rest = { b: 2 }
-** 正则表达式增强 **- 命名捕获组:/(?\d{4})-/ 可通过 groups.year 获取匹配值
- 反向断言:/(?<=¥)\d+/ 匹配 ¥ 后的数字(不包含 ¥ 本身)
- Unicode 转义:\p{Script=Greek} 匹配希腊文字符
###** ES2019(ES10)- 2019 年 **-Array.prototype.flat() / flatMap() 数组扁平化:
[1, [2, [3]]].flat(2); // [1, 2, 3](参数指定深度)
[1, 2].flatMap(x => [x, x*2]); // [1, 2, 2, 4]
-String.prototype.trimStart() / trimEnd() 精准去除字符串首尾空白(替代 trimLeft / trimRight)。
-Object.fromEntries() 将键值对数组转为对象(Object.entries 的逆操作):
Object.fromEntries([['a', 1], ['b', 2]]); // { a: 1, b: 2 }
-Symbol.prototype.description 获取 Symbol 的描述字符串:
const sym = Symbol('desc');
sym.description; // "desc"
###** ES2020(ES11)- 2020 年 - 可选链(?.)** 安全访问嵌套对象属性,避免 Cannot read property 'x' of undefined 错误:
const name = user?.address?.city; // 若 user 或 address 为 null/undefined,返回 undefined
-** 空值合并运算符(??)** 处理默认值(仅在左侧为 null/undefined 时生效,区别于 ||):
const score = 0 ?? 60; // 0(若用 || 会返回 60)
-** 动态导入(import())** 按需加载模块(返回 Promise):
button.addEventListener('click', () => {
import('./module.js').then(module => module.doSomething());
});
-BigInt 类型支持任意精度整数(解决 Number 最大安全值限制):
const big = 9007199254740993n; // 末尾加 n 表示 BigInt
-globalThis 统一全局对象引用(浏览器中是 window,Node.js 中是 global,统一为 globalThis)。
###** ES2021(ES12)- 2021 年 - 逻辑赋值运算符(||= / &&= / ??=)** 简化赋值逻辑:
// 等价于:if (!a) a = b
a ||= b;
// 等价于:if (a) a = b
a &&= b;
// 等价于:if (a === null/undefined) a = b
a ??= b;
-String.prototype.replaceAll() 替换字符串中所有匹配项(无需正则全局标志 g):
'aaa'.replaceAll('a', 'b'); // "bbb"
-** 数字分隔符(_)** 提升大数字可读性:
const num = 1_000_000_000; // 等价于 1000000000
-** Promise 新增方法(Promise.any())** 只要有一个 Promise 成功就返回其结果(与 Promise.all 相反):
Promise.any([fetch('url1'), fetch('url2')]).then(firstSuccess => ...);
###** ES2022(ES13)- 2022 年 - 类字段声明 **- 公有字段:class A { x = 1; }
- 私有字段(# 前缀,真正私有,外部无法访问):class A { #x = 1; }
-** 顶层 await** 在模块顶层直接使用 await(无需包裹在 async 函数中):
// module.js
const config = await fetch('/config');
export default config;
-Array.prototype.at() 支持负索引访问数组元素(替代 arr[arr.length - 1]):
[1, 2, 3].at(-1); // 3(最后一个元素)
-Object.hasOwn() 判断对象自身是否有某个属性(替代 Object.prototype.hasOwnProperty.call):
Object.hasOwn({ a: 1 }, 'a'); // true
###** ES2023(ES14)- 2023 年 - 数组查找从末尾开始(findLast() / findLastIndex())** 从数组末尾查找元素(避免反转数组):
[1, 2, 3, 2].findLast(x => x === 2); // 2(最后一个匹配项)
[1, 2, 3, 2].findLastIndex(x => x === 2); // 3
-toReversed() / toSorted() / toSpliced() / with() 数组的不可变操作(返回新数组,不修改原数组):
const arr = [3, 1, 2];
arr.toSorted(); // [1, 2, 3](原数组不变)
###** ES2024(ES15)- 2024 年 **-ArrayBuffer.prototype.transfer() 转移 ArrayBuffer 所有权(优化内存性能,避免复制):
const buf = new ArrayBuffer(1024);
const transferred = buf.transfer(); // 原 buf 失效
-Promise.withResolvers() 简化 Promise 控制(无需嵌套函数):
const { promise, resolve, reject } = Promise.withResolvers();
// 可在外部调用 resolve/reject
-** 正则表达式 v 标志 ** 增强 Unicode 匹配(支持属性逃逸和集合运算)。
总结
ES 每年的更新遵循 “小步快跑” 原则,聚焦解决实际开发痛点:
- 早期(2016-2019)以基础 API 补全为主(如 includes、flat)。
- 中期(2020-2022)引入革命性语法(?.、??、类私有字段)。
- 近期(2023-2024)侧重不可变操作和性能优化。
这些特性逐步提升了 JavaScript 的开发效率和安全性,同时保持了语言的向后兼容。