ES2020 新特性(种草)


Posted in Javascript onJanuary 12, 2020

这几年,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/

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

Javascript 相关文章推荐
jQuery load方法用法集锦
Dec 06 Javascript
jquery实现手机发送验证码的倒计时代码
Feb 12 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
Oct 17 Javascript
js的回调函数详解
Jan 05 Javascript
JavaScript中的toUTCString()方法使用详解
Jun 12 Javascript
javascript运动效果实例总结(放大缩小、滑动淡入、滚动)
Jan 08 Javascript
vue.js的安装方法
May 12 Javascript
Ionic项目中Native Camera的使用方法
Jun 07 Javascript
使用store来优化React组件的方法
Oct 23 Javascript
vue实现倒计时获取验证码效果
Apr 17 Javascript
VsCode里的Vue模板的实现
Aug 12 Javascript
教你使用vscode 搭建react-native开发环境
Jul 07 Javascript
在微信小程序中渲染HTML内容3种解决方案及分析与问题解决
Jan 12 #Javascript
es6 for循环中let和var区别详解
Jan 12 #Javascript
js 计数排序的实现示例(升级版)
Jan 12 #Javascript
JS实现动态无缝轮播
Jan 11 #Javascript
原生js实现无缝轮播图
Jan 11 #Javascript
JS实现轮播图效果
Jan 11 #Javascript
js实现带搜索功能的下拉框
Jan 11 #Javascript
You might like
php 采集书并合成txt格式的实现代码
2009/03/01 PHP
php中理解print EOT分界符和echo EOT的用法区别小结
2010/02/21 PHP
IIS+fastcgi下PHP运行超时问题的解决办法详解
2013/06/20 PHP
php中convert_uuencode()与convert_uuencode函数用法实例
2014/11/22 PHP
php微信公众号开发之二级菜单
2018/10/20 PHP
addRule在firefox下的兼容写法
2006/11/30 Javascript
JS 操作符整理[推荐收藏]
2011/11/15 Javascript
原生js的RSA和AES加密解密算法
2016/10/08 Javascript
jquery判断页面网址是否有效的两种方法
2016/12/11 Javascript
用director.js实现前端路由使用实例
2017/01/27 Javascript
vue仿element实现分页器效果
2018/09/13 Javascript
vue项目打包后怎样优雅的解决跨域
2019/05/26 Javascript
解决layui-open关闭自身窗口的问题
2019/09/10 Javascript
详解为element-ui的Select和Cascader添加弹层底部操作按钮
2020/02/07 Javascript
[07:54]DOTA2 MV《我的动力鞋》 ImbaTV 出品
2014/11/21 DOTA
[01:08:30]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第一场 2月28日
2021/03/11 DOTA
在Python中使用matplotlib模块绘制数据图的示例
2015/05/04 Python
Python闭包之返回函数的函数用法示例
2018/01/27 Python
python 实现将txt文件多行合并为一行并将中间的空格去掉方法
2018/12/20 Python
Django时区详解
2019/07/24 Python
python自动循环定时开关机(非重启)测试
2019/08/26 Python
在python Numpy中求向量和矩阵的范数实例
2019/08/26 Python
python中struct模块之字节型数据的处理方法
2019/08/27 Python
在pycharm中配置Anaconda以及pip源配置详解
2019/09/09 Python
python django中8000端口被占用的解决
2019/12/17 Python
浅谈django框架集成swagger以及自定义参数问题
2020/07/07 Python
应届毕业生应聘自荐信
2013/12/07 职场文书
岗位廉洁从政承诺书
2014/03/27 职场文书
村长贪污检举信
2014/04/04 职场文书
我的中国梦演讲稿高中篇
2014/08/19 职场文书
公司合并协议书范本
2014/09/30 职场文书
家庭财产分割协议范文
2014/11/24 职场文书
应急管理工作总结2015
2015/05/04 职场文书
2015年秋季灭鼠工作总结
2015/07/27 职场文书
2016年三严三实党课学习心得体会
2016/01/06 职场文书
八年级作文之我的母亲
2019/12/10 职场文书