一、 可选链式操作符 (?.)
安全的访问可能是 null 或 undefined 的属性,避免了因链式访问导致的错误。
const user = { address: { street: 'China' } };
// 传统方式
console.log(user.address ? user.address.street : undefined); // "China"
// Optional Chaining
console.log(user.address?.street); // "China"
// 当地址不存在时
const user2 = { name: 'Tom' };
console.log(user2.address?.street); // undefined
二、 空值合并操作符 (??)
仅在左操作符为 null 或 undefined 时提供默认值。
const a = undefined;
const b = a ?? 'Tom';
console.log(b); // 'Tom'
三、 动态 import(dynamic import)
允许在运行时通过 import() 函数动态加载模块,返回一个 Promise (支持代码分割和按需加载)
- 减少初始加载体积,提升页面性能(尤其适用于大型应用)
// 传统的静态导入:编译时加载,无论是否使用都会加载
import { utils } from './utils.js';
// 动态导入:运行时加载(如用户点击按钮时)
button.addEventListener('click', async () => {
/** 获取异步的模块 */
const module = await import('./utils.js');
module.utils.doMoreThing();
});
四、 BigInt 大整数类型
解决 JavaScript 中 Number 类型无法精确到表示超过 2 ** 53 - 1 (Number.MAX_SAFE_INTEGER) 的整数问题。
- 在数字后添加
n(如123n) - 使用
BigInt()构造函数(如BigInt(123))
// Number类型的精度问题
console.log(9007199254740992 === 9007199254740993); // true(错误,本应不等)
// BigInt解决精度问题
const bigNum1 = 9007199254740992n;
const bigNum2 = 9007199254740993n;
console.log(bigNum1 === bigNum2); // false(正确)
注意
- BigInt 不能直接与 Number 运算,需要显式转化
- 不支持
Math对象的方法(如Math.sqrt(4n)将报错)
五、 String.prototype.matchAll()
String.prototype.matchAll() 将返回一个迭代器,包含字符串中所有的正则表达式的匹配结果(包括捕获组),解决 match() 无法获取所有捕获组的问题。
const str = 'a1b2c3';
const regex = /(\w)(\d)/g;
// 传统match():只能获取匹配的整体,丢失捕获组
console.log(str.match(regex)); // ["a1", "b2", "c3"]
// matchAll():获取所有匹配及捕获组
for (const match of str.matchAll(regex)) {
console.log(match);
// 输出:
// ["a1", "a", "1", index: 0, input: "a1b2c3", groups: undefined]
// ["b2", "b", "2", index: 2, input: "a1b2c3", groups: undefined]
// ["c3", "c", "3", index: 4, input: "a1b2c3", groups: undefined]
}
六、 globalThis 统一全局对象访问
解决不同的环境下全局对象的不一致问题
- 浏览器:
window - Node.js:
global - Web Worker:
self
// 访问全局对象
// 在浏览器环境
七、 Promise.allSettled()
Promise.allSettled() 接受一个 Promise 数组,当所有的 Promise 都‘已决’(settled,无论成功 fulfilled 还是失败 rejected)时,返回一个新的 Promise ,结果包含每个 Promise 的状态和值。
信息
Promise.all() 是若是串联,当任意一个 Promise 失败时立即 reject,而 allSettled() 将等待所有的操作完成。
const promises = [
Promise.resolve('成功1'),
Promise.reject('失败1'),
Promise.resolve('成功2'),
];
// 等待所有Promise完成(无论成功/失败)
Promise.allSettled(promises).then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('成功:', result.value);
} else {
console.log('失败:', result.reason);
}
});
});
八、 模块化命名空间导出优化: export * as xx from "xxx module"
简化了模块的命名空间导出语法,无需先导入然后再导出。
// 传统写法:先导出再导出
import * as utils from './utils.js';
export { utils };
// ES2020 简化式写法
export * as utils from './utils.js';
九、 模块的元信息 import.meta
提供了 import.meta 来访问模块的元信息,目前主要支持 import.meta.url ,返回当前文件的 URL。
十、 for-in 枚举顺序标准化
此前,for-in 循环的枚举顺序未明确,不同的引擎实现不一致。ES2020 规范了枚举顺序:
- 先遍历对象自身的可枚举属性(按创建顺序)
- 再遍历原型链上的可枚举属性(按创建顺序)
- 忽略 Symbol 类型的属性