JavaScript 自 ES6(2015 年)发布后进入了快速发展的阶段,每年 ECMAScript 标准都会加入新特性。
ES7(2016 年)
-
指数运算符
**
使用**
来进行幂运算,代替Math.pow()
。console.log(2 ** 3); // 输出 8 console.log(10 ** -1); // 输出 0.1
-
Array.prototype.includes()
方法
includes()
用于检测数组中是否包含某个元素,返回布尔值。比indexOf()
更直观。const arr = [1, 2, 3]; console.log(arr.includes(2)); // 输出 true console.log(arr.includes(4)); // 输出 false
ES8(2017 年)
-
字符串填充:
padStart()
和padEnd()
用于在字符串的开头或结尾填充指定字符,使其达到特定长度。console.log('123'.padStart(5, '0')); // 输出 '00123' console.log('abc'.padEnd(6, 'x')); // 输出 'abcxxx'
-
Object.entries()
和Object.values()
Object.entries()
将对象转换为键值对数组。Object.values()
只返回对象的值。
const obj = { a: 1, b: 2 }; console.log(Object.entries(obj)); // 输出 [['a', 1], ['b', 2]] console.log(Object.values(obj)); // 输出 [1, 2]
-
异步函数
async/await
使得异步代码更接近同步代码的写法。async function fetchData() { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); }
ES9(2018 年)
-
Object.rest/spread
属性
...
语法用于对象属性的解构和扩展。const obj = { a: 1, b: 2, c: 3 }; const { a, ...rest } = obj; console.log(a); // 输出 1 console.log(rest); // 输出 { b: 2, c: 3 }
-
异步迭代器
for-await-of
用于处理异步可迭代对象。async function process(array) { for await (let item of array) { console.log(item); } }
-
正则表达式增强
s
修饰符:使.
可以匹配换行符。- Named Capture Groups:命名捕获组。
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const result = re.exec('2022-12-31'); console.log(result.groups.year); // 输出 '2022'
ES10(2019 年)
-
Array.prototype.flat()
和flatMap()
flat()
扁平化数组。flatMap()
结合了map()
和flat()
的功能。
const arr = [1, [2, [3]]]; console.log(arr.flat(2)); // 输出 [1, 2, 3]
-
Object.fromEntries()
将键值对数组转换为对象。const entries = [['a', 1], ['b', 2]]; console.log(Object.fromEntries(entries)); // 输出 { a: 1, b: 2 }
-
字符串裁剪:
trimStart()
和trimEnd()
console.log(' hello '.trimStart()); // 输出 'hello ' console.log(' hello '.trimEnd()); // 输出 ' hello'
ES11 (2020)
-
可选链操作符
?.
通过?.
简化访问嵌套对象属性,避免手动判断是否为null
或undefined
。const user = { profile: { name: 'Alice' } }; console.log(user?.profile?.name); // 输出 'Alice' console.log(user?.address?.city); // 输出 undefined
-
空值合并操作符
??
当变量为null
或undefined
时使用默认值。const name = null ?? '默认名'; console.log(name); // 输出 '默认名'
-
Promise.allSettled()
无论成功或失败,Promise.allSettled()
都会返回每个 Promise 的状态和结果。const promises = [Promise.resolve(1), Promise.reject('error')]; Promise.allSettled(promises).then(console.log); // 输出 [{status: "fulfilled", value: 1}, {status: "rejected", reason: "error"}]
-
大整数类型
BigInt
BigInt
支持处理比Number
更大的整数。const big = 123456789012345678901234567890n; console.log(big + 1n); // 输出 123456789012345678901234567891n
-
动态
import()
动态加载模块而不阻塞代码执行,适用于延迟加载。import('./module.js').then(module => module.doSomething());
-
globalThis
提供全局作用域下的统一访问方式,在不同环境下 (如浏览器、Node.js) 都能使用。console.log(globalThis);
ES12 (2021)
-
逻辑赋值运算符
包含三种新运算符:||=
,&&=
,??=
,简化赋值逻辑。let count = 0; count ||= 5; // 当 count 为 falsy 值时赋值 5 console.log(count); // 输出 5
-
数字分隔符
_
数字中可以添加下划线_
,提高可读性。const billion = 1_000_000_000; console.log(billion); // 输出 1000000000
-
String.prototype.replaceAll()
替换字符串中所有出现的指定字符或子串。console.log('apple pie'.replaceAll('p', 'b')); // 输出 'abble bie'
-
Promise.any()
返回第一个成功的 Promise,若全部失败则抛出错误。const promises = [Promise.reject('Error'), Promise.resolve(1)]; Promise.any(promises).then(console.log); // 输出 1
-
WeakRef 和 FinalizationRegistry
允许创建弱引用对象的引用,当对象没有被其他地方引用时自动清除。const registry = new FinalizationRegistry(() => console.log('Object collected'));
ES13 (2022)
-
顶层
await
允许在模块顶层使用await
,无需封装在异步函数中。const response = await fetch('/data'); const data = await response.json(); console.log(data);
-
Array.prototype.at()
提供基于负索引的访问方式。const arr = [10, 20, 30]; console.log(arr.at(-1)); // 输出 30
-
Object.hasOwn()
直接检查对象是否包含指定的属性,类似hasOwnProperty
。const obj = { a: 1 }; console.log(Object.hasOwn(obj, 'a')); // 输出 true
-
私有字段增强
类的私有字段可以被#
开头的符号定义,仅供类内部访问。class MyClass { #privateField = 42; getPrivate() { return this.#privateField; } }
ES14 (2023)
-
Array.prototype.findLast()
和Array.prototype.findLastIndex()
找到数组中符合条件的最后一个元素或索引。const arr = [1, 2, 3, 4]; console.log(arr.findLast(x => x % 2 === 0)); // 输出 4 console.log(arr.findLastIndex(x => x % 2 === 0)); // 输出 3
-
Symbols 作为
WeakMap
和WeakSet
的键
支持将 Symbol 用作WeakMap
和WeakSet
的键,使得其使用场景更加广泛。 -
精确的 ECMAScript 模块解析
允许在导入模块时提供更灵活的路径控制,可以在不同平台上导入模块。
ES15 (2024)
-
Object.groupBy() 和 Map.groupBy()
Object.groupBy()
和Map.groupBy()
可以按条件对数据进行分组。以下示例展示如何使用Object.groupBy()
来根据对象数组中的年龄分组:const people = [ { name: "Alice", age: 25 }, { name: "Bob", age: 30 }, { name: "Charlie", age: 25 } ]; const groupedByAge = Object.groupBy(people, person => person.age); console.log(groupedByAge); // 输出: // { // 25: [{ name: "Alice", age: 25 }, { name: "Charlie", age: 25 }], // 30: [{ name: "Bob", age: 30 }] // }
-
Temporal API
Temporal
API 提供了一种更强大和可靠的日期时间处理方式,避免了 Date 对象的跨时区问题。下面是如何创建一个特定日期对象的示例:const date = Temporal.PlainDate.from({ year: 2024, month: 11, day: 14 }); console.log(date.toString()); // 输出: 2024-11-14
如果需要时区转换,可以使用
Temporal.ZonedDateTime
:const zonedDateTime = Temporal.ZonedDateTime.from("2024-11-14T10:00:00[Asia/Tokyo]"); console.log(zonedDateTime.toString()); // 输出: 2024-11-14T10:00:00+09:00[Asia/Tokyo]
-
String.toWellFormed() 和 String.isWellFormed()
String.toWellFormed()
用于将不完整的代理对转化为有效字符串,String.isWellFormed()
用于检查字符串是否有效。例如:const str = "abc\uD800"; console.log(str.isWellFormed()); // 输出: false console.log(str.toWellFormed()); // 输出: "abc�"
-
Promise.withResolvers()
Promise.withResolvers()
简化了 Promise 创建过程,将 Promise、resolve 和 reject 合并成一行,方便异步操作:const { promise, resolve, reject } = Promise.withResolvers(); promise.then(value => { console.log("Resolved with:", value); }); resolve("Success!"); // 输出: Resolved with: Success!
-
Atomics.waitAsync()
Atomics.waitAsync()
在共享内存上进行异步等待操作,避免了主线程阻塞。在共享的Int32Array
上使用它,如下示例所示:const sharedBuffer = new SharedArrayBuffer(4); const int32 = new Int32Array(sharedBuffer); Atomics.store(int32, 0, 0); Atomics.waitAsync(int32, 0, 0).then(() => { console.log("Async wait completed"); }); Atomics.store(int32, 0, 1); // 解除等待条件