ES2020新特性

180 阅读4分钟

JavaScript 的 ES2020 版本新功能有:

➡️ String.prototype.matchAll

➡️ import()

按需加载,webpack已解决。

➡️ BigInt

➡️ Promise.allSettled

➡️ globalThis

➡️ for-in mechanics

➡️ 可选链

➡️ 空值合并运算符

可选链操作符

可选链 可让我们在查询具有多个层级的对象时,不再需要进行冗余的各种前置校验

背景:当需要访问嵌套在对象内部好几层的属性时,可能就会得到臭名昭著的错误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;

空位合并操作符

背景:当我们查询某个属性时,经常会给没有该属性就设置一个默认的值。

例如

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

Promise.allSettled

Promise.all 具有并发执行异步任务的能力。但它的最大问题就是如果其中某个任务出现异常(reject),所有任务都会挂掉,Promise直接进入 reject 状态。

场景:你的页面有三个区域,分别对应三个独立的接口数据,使用 Promise.all 来并发三个接口,如果其中任意一个接口服务异常,状态是reject,这会导致页面中该三个区域数据全都无法渲染出来,因为任何 reject 都会进入catch回调, 很明显,这是无法接受的。

Promise.all([
    Promise.reject({code: 500, msg: '服务异常'}),
    Promise.resolve({ code: 200, list: []}),
    Promise.resolve({code: 200, list: []})
])
.then((ret) => {
    // 如果其中一个任务是 reject,则不会执行到这个回调。
    RenderContent(ret);
})
.catch((error) => {
    // 本例中会执行到这个回调
    // error: {code: 500, msg: "服务异常"}
})

如果并发任务中,无论一个任务正常或者异常,都会返回对应的的状态(fulfilled 或者 rejected)与结果(业务value 或者 拒因 reason),在 then 里面通过 filter 来过滤出想要的业务逻辑结果,这就能最大限度的保障业务当前状态的可访问性,而 Promise.allSettled 就是解决这问题的。

Promise.allSettled([
    Promise.reject({code: 500, msg: '服务异常'}),
    Promise.resolve({ code: 200, list: []}),
    Promise.resolve({code: 200, list: []})
])
.then((ret) => {
    /*
        0: {status: "rejected", reason: {…}}
        1: {status: "fulfilled", value: {…}}
        2: {status: "fulfilled", value: {…}}
    */
    // 过滤掉 rejected 状态,尽可能多的保证页面区域数据渲染
    RenderContent(ret.filter((el) => {
        return el.status !== 'rejected';
    }));
});

BigInt

Js 中 Number类型只能安全的表示-(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

解决此问题,ES2020提供一种新的数据类型:BigInt。 使用 BigInt 有两种方式:

1:在整数字面量后面加n。

var bigIntNum = 9007199254740993n;

2:使用 BigInt 函数。

var bigIntNum = BigInt(9007199254740);
var anOtherBigIntNum = BigInt('9007199254740993');

注意: 1. BigInt 是一种新的数据原始(primitive)类型。

typeof 9007199254740993n; // -> 'bigint'