ES2020新增功能
globalThis 对象
在JavaScript
运行环境中,存在一个顶层对象,即是全局运行环境(全局作用域),在browser
环境下,顶层对象指向window
,在node
环境下,顶层对象指向global
,在Web Worker
中,顶层对象又指向self
。而这个顶层对象我们常常又使其与this
挂钩,一般默认使用this
变量即可获得该顶层变量。但由于this
在JavaScript
中又是一个很复杂的变量。因为this
在不同的执行上下文中指向不一,使其在获取顶层对象具有局限性。如在模块中,this
指向该模块;严格模式运行的函数this
是undefined
。因此,出现很多垫片函数获取全局的对象,我们最熟悉的是如下获取顶层对象的方法。
function getGloablThis() {
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');
}
在ES2020
中,提供了globalThis
对象作为标准化的方式获取顶层对象。但目前由于浏览器支持情况的差异在使用时,可能需要垫片函数(如global-this)。
// chrome 中打印 glbalThis 对象
console.dir(globalThis)
输出结果如下:
新数据类型 bigint
在面试中我们经常会遇到0.1 + 0.2 !== 0.3
,这是为什么,又如何使其相等。当然了我们并不是为了解决这个问题才引入新的数据类型。我们知道JavaScript
中数字都是采用64位进行存储的,因此其是有精度有范围的。这也是为什么0.1 + 0.2 !== 0.3
,而且范围仅在Number.MIN_SAFE_INTEGER(9007199254740991)``Number.MAX_SAFE_INTEGER(-9007199254740991)
之间可使用,因此,在一定的使用场景中是十分首先。为此,ES2020
引入了一种新的数据类型bigint
。
const big = 123456789n;
typeof big; // bigint
bigint
使用也比较简单就是在数据后面加上n
表示其是bigint
类型的数据。与Number
类似,ES2020
也提供了原生的BigInt
构造函数,用于将其他类型数据转换成bigint
数据。
const big = BigInt(Number.MAX_SAFE_INTEGER) // 9007199254740991n
Promise.allSettled
Promise.all
在执行并发异步任务是,只有所有的Promise
都是fulfilled
状态时,其才是fulfilled
状态,只要有一个并发的Promise
被rejected
,其状态就是rejected
的。而这常常无法满足我们的业务场景,比如,我们使用Promise.all
并发的请求三个没有关联的API
接口获取数据,不能因为其中一个接口报错,而无法返回其他接口的数据,这是不合理的。因此,ES2020
引入Promise.allSettled
,Promise.allSettled
方法接受一组Promise
实例作为参数,包装成一个新的Promise
实例。在进行并发处理时,不管其中入参Promise
实例状态如何,只要所有的Promise
实例都是完结状态,其就返回所有的实例结果数据无论其是fulfilled
或rejected
。
const promises = [
fetch('index.html'),
fetch('index.js'),
fetch('index.css')
]
const promiseallSettled = Promise.allSettled(promises);
promiseallSettled.then(res => {
const successRes = res.filter(item => item.status === 'fulfilled');
const errorRes = res.filter(item => item.status === 'rejected');
return {successRes, errorRes};
})
String.prototype.matchAll
ES2020
增加了String.prototype.matchAll
方法,一次性取出所有匹配,返回一个遍历器(Iterator)。
const source = 'this is test1 test2 test3!';
const reg = /test(\d)/g;
for (const match of source.matchAll(reg)) {
console.log(match);
}
输出结果如下:
可选链
在实际开发中,我们常常会读取对象内部的某个属性,但我们需要做前置检查,判断该对象是否存在,如果需要查询具有多层级的对象时,这种检查就更复杂。
const userName = user && user.detail && user.detail.name;
或者使用三元运算符
const userName = user ? (user.detail ? user.detail.name : '') : '';
这种层层判断非常的麻烦, ES2020
引入了“链判断运算符”(optional chaining operator)?.
,简化上面的操作,不再需要进行冗余的各种前置校验。
const userName = user?.detail?.name;
使用了?.
运算符时,当左侧的对象为nul
l或undefined
就不再往下运算,而是返回undefined
。
空值合并
在实际开发场景中,我们经常遇到为变量指定一个默认值的情况。有时我们的意愿常常是当某个属性的值是null
或undefined
时,默认值才生效。但实际情况是经常是当值为falsy
(faly值 (虚值) 是在Boolean
上下文中认定为false
的值)值时默认值就生效,而不仅仅只有null
或undefined
时生效。
const userName = name || 'testName';
// 当name为faly时,默认值就生效了
ES2020
引入??
运算符。只有运算符左侧的值为null
或undefined
时,才会返回右侧的值。
const userName = name ?? 'testName';
??
运算符与?.
运算符配合使用,可以为null
或undefined
的值设置默认值。
const userName = user?.detail?.name ?? 'testName';