ES2020 新特性(种草)

这几年,Ecma TC39一年一次更新 ecmascript 规范标准,截止目前,以下特性已进入 finished 状态。现在带大家体验种草 ES2020 新特性。

一:Promise.allSettled

Promise.all 缺陷

都知道 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';
  }));
});

二:可选链(Optional chaining)

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

日常开发中,我们经常会遇到这种查询

var name = user && user.info && user.info.name;

又或是这种

var age = user && user.info && user.info.getAge && user.info.getAge();

这是一种丑陋但又不得不做的前置校验,否则很容易命中 Uncaught TypeError: Cannot read property... 这种错误,这极有可能让你整个应用挂掉。

用了 Optional Chaining ,上面代码会变成

var name = user?.info?.name;
var age = user?.info?.getAge?.();

可选链中的 ? 表示如果问号左边表达式有值, 就会继续查询问号后面的字段。根据上面可以看出,用可选链可以大量简化类似繁琐的前置校验操作,而且更安全。

三:空值合并运算符(Nullish coalescing Operator)

当我们查询某个属性时,经常会遇到,如果没有该属性就会设置一个默认的值。比如下面代码中查询玩家等级。

var level = (user.data && user.data.level) || '暂无等级';

在JS中,空字符串、0 等,当进行逻辑操作符判时,会自动转化为 false。在上面的代码里,如果玩家等级本身就是 0 级, 变量 level 就会被赋值 暂无等级 字符串,这是逻辑错误。

var level;
if (typeof user.level === 'number') {
  level = user.level;
} else if (!user.level) {
  level = '暂无等级';
} else {
  level = user.level;
}

来看看用空值合并运算符如何处理

// {
//  "level": 0
// }
var level = `${user.level}级` ?? '暂无等级';
// level -> '0级'

用空值合并运算在逻辑正确的前提下,代码更加简洁。

空值合并运算符 与 可选链 相结合,可以很轻松处理多级查询并赋予默认值问题。

var level = user.data?.level ?? '暂无等级';

四:dynamic-import

按需 import 提案几年前就已提出,如今终于能进入ES正式规范。这里个人理解成“按需”更为贴切。现代前端打包资源越来越大,打包成几M的JS资源已成常态,而往往前端应用初始化时根本不需要全量加载逻辑资源,为了首屏渲染速度更快,很多时候都是按需加载,比如懒加载图片等。而这些按需执行逻辑资源都体现在某一个事件回调中去加载。

el.onclick = () => {
  import(`/path/current-logic.js`)
  .then((module) => {
    module.doSomthing();
  })
  .catch((err) => {
    // load error;
  })
}

当然,webpack目前已很好的支持了该特性。

五:globalThis

Javascript 在不同的环境获取全局对象有不通的方式,node 中通过 global, web中通过 window, self 等,有些甚至通过 this 获取,但通过 this 是及其危险的,this 在 js 中异常复杂,它严重依赖当前的执行上下文,这些无疑增加了获取全局对象的复杂性。

过去获取全局对象,可通过一个全局函数

var 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');
}; 

var globals = getGlobal(); 

// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/globalThis

而 globalThis 目的就是提供一种标准化方式访问全局对象,有了 globalThis 后,你可以在任意上下文,任意时刻都能获取到全局对象。

六: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 有两种方式:

在整数字面量后面加n。

var bigIntNum = 9007199254740993n;

使用 BigInt 函数。

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

通过 BigInt, 我们可以安全的进行大数整型计算。

var bigNumRet = 9007199254740993n + 9007199254740993n; // -> -> 18014398509481986n

bigNumRet.toString(); // -> '18014398509481986'

注意:

BigInt 是一种新的数据原始(primitive)类型。

typeof 9007199254740993n; // -> 'bigint'

尽可能避免通过调用函数 BigInt 方式来实例化超大整型。因为参数的字面量实际也是 Number 类型的一次实例化,超出安全范围的数字,可能会引起精度丢失。

七:String.prototype.matchAll

思考下面代码

var str = '<text>JS</text><text>正则</text>';
var reg = /<\w+>(.*?)<\/\w+>/g;

console.log(str.match(reg));
// -> ["<text>JS</text>", "<text>正则</text>"]

可以看出返回的数组里包含了父匹配项,但未匹配到子项(group)。移除全局搜索符“g”试试。

var str = '<text>JS</text><text>正则</text>';
// 注意这里没有全局搜素标示符“g”
var reg = /<\w+>(.*?)<\/\w+>/;
console.log(str.match(reg));

// 上面会打印出
/*
[
  "<text>JS</text>",
  "JS",
  index: 0,
  input:
  "<text>JS</text><text>正则</text>",
  groups: undefined
]
*/

这样可以获取到匹配的父项,包括子项(group),但只能获取到第一个满足的匹配字符。能看出上面无法匹配到<text>正则</text>。

如果获取到全局所有匹配项,包括子项呢?

ES2020提供了一种简易的方式:String.prototype.matchAll, 该方法会返回一个迭代器。

var str = '<text>JS</text><text>正则</text>';
var allMatchs = str.matchAll(/<\w+>(.*?)<\/\w+>/g);

for (const match of allMatchs) {
 console.log(match);
}

/*
第一次迭代返回:
[
  "<text>JS</text>",
  "JS",
  index: 0,
  input: "<text>JS</text><text>正则</text>",
  groups: undefined
]

第二次迭代返回:
[
  "<text>正则</text>",
  "正则",
  index: 15,
  input: "<text>JS</text><text>正则</text>",
  groups: undefined
]
*/

能看出每次迭代中可获取所有的匹配,以及本次匹配的成功的一些其他元信息。

参考资料

github.com/tc39/proposals/blob/master/finished-proposals.md
prop-tc39.now.sh/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ES6新特性之模块Module用法详解

    本文实例讲述了ES6新特性之模块Module用法.分享给大家供大家参考,具体如下: 一.Module简介 ES6的Class只是面向对象编程的语法糖,升级了ES5的构造函数的原型链继承的写法,并没有解决模块化问题.Module功能就是为了解决这个问题而提出的. 历史上,JavaScript一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来.其他语言都有这项功能. 在ES6之前,社区制定了一些模块加载方案,最主要的有CommonJS和AMD两种.前者用

  • ES6新特性七:数组的扩充详解

    本文实例讲述了ES6新特性之数组的扩充.分享给大家供大家参考,具体如下: 1. Array.from() 1) Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map,他们都部署了iterator接口,字符串也是). let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; // ES5的写法 var arr

  • ES6新特性之字符串的扩展实例分析

    本文实例讲述了ES6新特性之字符串的扩展.分享给大家供大家参考,具体如下: 一.ES5字符串函数 concat: 将两个或多个字符的文本组合起来,返回一个新的字符串. indexOf: 返回字符串中一个子串第一处出现的索引(从左到右搜索).如果没有匹配项,返回 -1 . charAt: 返回指定位置的字符. lastIndexOf: 返回字符串中一个子串最后一处出现的索引(从右到左搜索),如果没有匹配项,返回 -1 . match: 检查一个字符串匹配一个正则表达式内容,如果么有匹配返回 nul

  • ES6新特性之类(Class)和继承(Extends)相关概念与用法分析

    本文实例讲述了ES6新特性之类(Class)和继承(Extends)相关概念与用法.分享给大家供大家参考,具体如下: 一.类(Class) 1.基本语法 JavaScript语言的传统方法是通过构造函数,定义并生成新对象.下面是一个例子 function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'

  • ES6中非常实用的新特性介绍

    ECMAScript 6离我们越来越近了,作为它最重要的方言,Javascript也即将迎来语法上的重大变革,InfoQ特开设"深入浅出ES6"专栏,来看一下ES6将给我们带来哪些新内容. 写在前面 ES6 已经提交给 Ecma 大会审查了,也就是说,我们将迎来一大波 javascript 的最新标准,还有一些语法糖.ES6 中有很多值得我们关注的东西,下面是我发现的一些我们最常用的一些新特性,进行记录一下. 1. for-of循环 这个东西用来循环数组很爽,原因呢,是因为它弥补了目前

  • JavaScript ES6的新特性使用新方法定义Class

    ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本了).上一次标准的制订还是2009年出台的ES5.目前ES6的标准化工作正在进行中,预计会在14年12月份放出正式敲定的版本.但大部分标准已经就绪,且各浏览器对ES6的支持也正在实现中. ES6中定义类的方式, 就是ES3和ES5中定义类的语法糖,虽然也有些区别,但是整体定义类的方式更加简洁,类的继承更加方便, 如果想对ES6中的继承更加

  • JavaScript中的Reflect对象详解(ES6新特性)

    Reflect介绍: Reflect这个对象在我的node(v4.4.3)中还没有实现, babel(6.7.7)也没有实现 ,新版本的chrome是支持的, ff比较早就支持Proxy和Reflect了,要让node支持Reflect可以安装harmony-reflect ; Reflect不是构造函数, 要使用的时候直接通过Reflect.method()调用, Reflect有的方法和Proxy差不多, 而且多数Reflect方法原生的Object已经重新实现了. 什么要使用Reflect

  • ES6新特性八:async函数用法实例详解

    本文实例讲述了ES6新特性之async函数用法.分享给大家供大家参考,具体如下: 1. async 函数是什么? node.js 版本7及之后版本才支持该函数. 可以简单的理解为他是Generator 函数的语法糖,即Generator 函数调用next() 返回的结果. ① Generator 函数需要next() 或执行器进行执行,而async 函数只需和普通函数一样执行. ② async和await,比起星号和yield,语义更清楚了.async表示函数里有异步操作,await表示紧跟在后

  • ES6新特性之变量和字符串用法示例

    本文实例讲述了ES6新特性之变量和字符串用法.分享给大家供大家参考,具体如下: 一.变量 1. LET 我们都习惯用var 来声明变量,现在还可以用let来声明变量,两者的主要区别是作用域:var声明的变量作用域为包围它的函数,而let声明的变量作用域仅在它所在的块中.(在ES5中是没有块的概念的). if(true){ let a=1; } console.log(a);//undifined 这样使代码更加干净,减少滞留的变量,再如我们经常用的数组遍历: for(let i=0;i<list

  • ES6的新特性概览

    Nick Justice是GitHub开发者计划的一员.早在ES6语言标准发布之前,他就借助像Babel这样的转译器以及最新版本的浏览器在自己的项目中使用ES6特性.他认为,ES6的新特性将极大地改变JavaScript的编写方式. ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本了).上一次标准的制订还是2009年出台的ES5.目前ES6的标准化工作正在进行中,预计会在14年12月份

随机推荐