ES2020 新特性详解:可选链、空值合并与 BigInt 等核心更新
本文详解 ES2020 (ECMAScript 2020) 引入的七大核心新特性。重点解析可选链操作符(?.)简化嵌套对象访问,空位合并操作符(??)精准处理默认值,以及 Promise.allSettled 确保异步任务状态获取。同时涵盖动态 import() 实现按需加载、BigInt 支持超大整数计算、String.prototype.matchAll 高效正则匹配及 globalThis 统一全局对象访问,助力开发者提升代码安全性与性能。
ES2020 概述与前言
引言部分
ES2020 即 ECMAScript 2020 年度版本。相较于 ES6 (ES2015) 的大规模更新,该版本特性较少,但仍包含诸多实用功能。欲查阅更多高质量内容,请访问我的博客。
本文通过简洁的代码示例解析 ES2020 新特性,旨在帮助读者快速理解新功能,无需复杂阐述。
可选链操作符 (Optional Chaining)
可选链操作符(Optional Chaining)
可选链机制允许在访问多层级对象属性时,免除繁琐的前置校验步骤。
开发中访问深层嵌套对象属性时,常遭遇臭名昭著的错误Uncaught TypeError: Cannot read property...,此类错误会导致程序中断运行。

因此,需修改代码以处理属性链中可能出现的 undefined 对象,例如:
let nestedProp = obj && obj.first && obj.first.second;
在访问 obj.first.second 前,必须确保 obj 及 obj.first 非 null(且非 undefined)。
借助可选链式调用,可大幅简化此类繁琐的前置校验,同时提升安全性:
let nestedProp = obj?.first?.second;
若 obj 或 obj.first 为 null/undefined,表达式将执行短路计算并直接返回 undefined。
可选链操作符的浏览器支持情况如下:

空位合并操作符 (Nullish Coalescing Operator)
空位合并操作符(Nullish coalescing Operator)
查询属性时,常需为缺失属性设置默认值,常见方式如下:
let c = a ? a : b // 方式1
let c = a || b // 方式2
上述方式存在明显缺陷,即会覆盖所有假值(如 0、''、false),而这些值在某些场景下可能是有效输入。
let x = {
profile: {
name: '浪里行舟',
age: ''
}
}
console.log(x.profile.age || 18) //18
前述示例中,age 属性为空字符串却被视为假值。为此,ES2020 引入空位合并操作符(??)。当 ?? 左侧表达式求值为 undefined 或 null 时,返回右侧默认值。
let c = a ?? b;
// 等价于let c = a !== undefined && a !== null ? a : b;
示例代码如下:
const x = null;
const y = x ?? 500;
console.log(y); // 500
const n = 0
const m = n ?? 9000;
console.log(m) // 0
空位合并操作符的浏览器支持情况如下:

Promise.allSettled 异步处理
Promise.allSettled
Promise.all 具备并发执行异步任务的能力,但其最大缺陷在于:若参数中任一 promise 为 reject 状态,整个 Promise.all 调用将立即终止,并返回一个 reject 状态的 Promise 对象。
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.reject('error')
];
Promise.all(promises)
.then(responses => console.log(responses))
.catch(e => console.log(e)) // "error"
假设存在如下场景:页面包含三个区域,分别对应三个独立接口数据。使用 Promise.all 并发请求这三个接口时,若任一接口异常(状态为 reject),将导致三个区域数据均无法显示。此状况难以接受,而 Promise.allSettled 的出现恰好解决了这一痛点:
Promise.allSettled([
Promise.reject({ code: 500, msg: '服务异常' }),
Promise.resolve({ code: 200, list: [] }),
Promise.resolve({ code: 200, list: [] })
]).then(res => {
console.log(res)
/*
0: {status: "rejected", reason: {…}}
1: {status: "fulfilled", value: {…}}
2: {status: "fulfilled", value: {…}}
*/
// 过滤掉 rejected 状态,尽可能多的保证页面区域数据渲染
RenderContent(
res.filter(el => {
return el.status !== 'rejected'
})
)
})
Promise.allSettled 与 Promise.all 类似,参数接受 Promise 数组,返回新 Promise。其唯一区别在于不进行短路处理,即当所有 Promise 处理完毕后,无论成功与否,均可获取每个 Promise 的状态。
Promise.allSettled 的浏览器支持情况如下:

String.prototype.matchAll 正则匹配
String.prototype.matchAll
若正则表达式在字符串中存在多个匹配,通常需使用 g 或 y 修饰符,并在循环中逐一提取。
function collectGroup1 (regExp, str) {
const matches = []
while (true) {
const match = regExp.exec(str)
if (match === null) break
matches.push(match[1])
}
return matches
}
console.log(collectGroup1(/"([^"]*)"/g, `"foo" and "bar" and "baz"`))
// [ 'foo', 'bar', 'baz' ]
值得注意的是,若无 /g 修饰符,.exec() 仅返回第一个匹配。现通过 String.prototype.matchAll 方法,可一次性提取所有匹配结果。
function collectGroup1 (regExp, str) {
let results = []
for (const match of str.matchAll(regExp)) {
results.push(match[1])
}
return results
}
console.log(collectGroup1(/"([^"]*)"/g, `"foo" and "bar" and "baz"`))
// ["foo", "bar", "baz"]
上述代码中,string.matchAll(regex) 返回遍历器,故可使用 for...of 循环提取。
String.prototype.matchAll 的浏览器支持情况如下:

Dynamic import 动态导入
Dynamic import
当前前端打包资源日益庞大,应用初始化时无需加载全部逻辑资源。为提升首屏渲染速度,常采用动态导入(按需加载)模块,如懒加载图片,从而优化应用性能。
按需加载逻辑资源通常在特定事件回调中执行:
el.onclick = () => {
import('/modules/my-module.js')
.then(module => {
// Do something with the module.
})
.catch(err => {
// load error;
})
}
import() 可用于 script 脚本中,import(module) 函数可在任意位置调用,并返回解析为模块对象的 Promise。
此种使用方式同样支持 await 关键字。
let module = await import('/modules/my-module.js');
通过动态导入代码,可减少应用加载时间,并尽可能快地向用户返回内容。
Dynamic import 的浏览器支持情况如下:

BigInt 大整数支持
BigInt
JavaScript 在数学运算方面存在局限,仅能安全表示-(2^53-1)至 2^53-1 范围内的值,即Number.MIN_SAFE_INTEGER 至Number.MAX_SAFE_INTEGER。超出此范围的整数计算或表示将丢失精度。
var num = Number.MAX_SAFE_INTEGER; // -> 9007199254740991
num = num + 1; // -> 9007199254740992
// 再次加 +1 后无法正常运算
num = num + 1; // -> 9007199254740992
// 两个不同的值,却返回了true
9007199254740992 === 9007199254740993 // -> true
为此,BigInt 应运而生,作为第7个原始类型,支持安全的大数整型计算。可在 BigInt 上使用与普通数字相同的运算符,如 +, -, /, *, % 等。
创建 BigInt 类型值十分简便,只需在数字后添加 n 即可,例如 123 变为 123n。亦可使用全局方法 BigInt(value) 进行转换,参数 value 为数字或数字字符串。
const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"
只要在数字末尾添加 n,即可正确计算大数:
1234567890123456789n * 123n;
// -> 151851850485185185047n
然而存在一个问题:在大多数操作中,BigInt 与 Number 不可混合使用。比较 Number 和 BigInt 是允许的,但不可将它们相加。
1n < 2
// true
1n + 2
// Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
BigInt 的浏览器支持情况如下:

globalThis 全局对象访问
globalThis
globalThis 是一种获取全局 this 的全新标准方法。此前开发者通过以下方式获取:
- 全局变量 window:经典的全局对象获取方法,但在 Node.js 和 Web Workers 中不可用。
- 全局变量 self:通常仅在 Web Workers 和浏览器中生效,不支持 Node.js。部分开发者通过判断 self 是否存在来识别代码运行环境(Web Workers 或浏览器)。
- 全局变量 global:仅在 Node.js 中生效。
过去获取全局对象,可通过一个全局函数:
// ES10之前的解决方案
const getGlobal = function(){
if(typeof self !== 'undefined') return self
if(typeof window !== 'undefined') return window
if(typeof global !== 'undefined') return global
throw new Error('unable to locate global object')
}
// ES10内置
globalThis.Array(0,1,2) // [0,1,2]
// 定义一个全局对象v = { value:true } ,ES10用如下方式定义
globalThis.v = { value:true }
globalThis 旨在提供一种标准化方式访问全局对象。使用 globalThis 后,可在任意上下文、任意时刻获取全局对象。
若运行环境为浏览器,globalThis 指向 window;若在 Node 环境中,globalThis 指向 global。因此,无需再考虑不同环境差异。
// worker.js
globalThis === self
// node.js
globalThis === global
// browser.js
globalThis === window
新提案规定,Object.prototype 必须位于全局对象的原型链中。以下代码在最新浏览器中已返回 true:
Object.prototype.isPrototypeOf(globalThis); // true
globalThis 的浏览器支持情况如下:

参考资料与结语
参考文章
TC39 Proposals
MDN文档
种草 ES2020 新特性
ES2020 Features in simple examples
New Features In ES2020 You Should Check
5 ECMAScript Proposals To Look Out For In ES2020
以上为本文全部内容,希望对各位学习有所帮助,也希望大家多多支持本站。
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
