写点什么

ECMAScript 2020(ES11) 新特性简介

发布于: 2 小时前

简介

ES11 是 ECMA 协会在 2020 年 6 月发行的一个版本,因为是 ECMAScript 的第十一个版本,所以也称为 ES11.

今天我们讲解一下 ES11 的新特性。

ES11 引入了 9 个新特性,我们接下来一一讲解。

动态 imports

在 ES11 之前,我们可以使用下面的方式进行模块的导入:

import * as TestModule from "./test-module.js";

复制代码

但是上面的导入方式会有一些问题,首先是效率的问题,所有的 module 都需要在首次加载的时候导入,会导致程序效率的降低。另外上面的模块名字是写死的,不可以在程序运行的时候进行动态修改。

也就是说上面的模块导入方式,不能对模块进行动态导入,或者按需导入,在使用上有诸多的不便。

为了解决这个问题,ES11 引入了新的 import() 方法,使用这个方法,你可以对模块进行动态导入,并且通过设置模块名为变量的形式,可以对模块名进行动态修改,非常的神奇。我们看一个具体的使用例子:

const baseModulePath = "./baseModules";const btnImportModule = document.getElementById("btnImportModule");let userList = [];
btnImportModule.addEventListener("click", async e => { const userModule = await import(`${baseModulePath}/users.js`);
userList = userModule.getUsers();});

复制代码

上面代码中我们定义了一个基本的 Module 路径,通过点击页面上的按钮,可以动态的加载一个 users.js 模块,然后调用该模块的 getUsers()方法,获得 userList 列表。

import.meta

除了动态引入模块之外,import 还提供了一个元属性 meta,它包含了当前引入的模块的信息,目前他里面有一个 url 属性,代表模块被引用的 URL。如果想使用 URL 信息,那么可以在代码中使用 import.meta.url。

export 加强

import 是在 ECMAScript 2015 中引入的,主要被用来做模块的引入,import 可以引入整个模块,也可以引入部分模块。如下所示:

import {something} from "./test-module.js";import * from "./test-module.js";

复制代码

和 import 对应的就是 export,同样可以 export 所有或者部分,如下所示:

export {something} from "./test-module.js";export * from "./test-module.js";

复制代码

通常情况来说,上面讲的 import 和 export 已经够用了,但是对于导出模块需要重命名的情况,我们不能直接导出,而是必须先在 import 的时候进行重命名,然后再使用 export 将重命名的模块导出:

import * as myModule from "./test-module.js";export {myModule};
复制代码

如果使用 export 的增强,则不需要使用 import,直接使用 export 导出即可:

export * as {myModule} from "./test-module.js";
复制代码

BigInt

ES11 引入了新的数据类型 BigInt,在这之前,javascript 中表示数字的对象是 Number,它可以表示 64-bit 的浮点类型数字。当然它也可以代表整数,但是整数表示的最大值是 2^53,也可以用 Number.MAX_SAFE_INTEGER 来表示。

一般来说 Number 已经够用了,但是如果在某些情况下需要对 64-bit 的整数进行存储或者运算,或者要表示的范围超过了 64-bit 的话,Number 就不够用了。

怎么办呢?如果只是存储的话,可以存储为字符串,但是第二种字符串就不适用了。于是引入了 BigInt 来解决这个问题。要表示 BigInt,只需要在数字的后面加上 n 即可。

const bigInt = 112233445566778899n;

复制代码

或者使用构造函数来构造 bigInt:

const bigInt = BigInt("112233445566778899");

复制代码

可以使用 typeof 来查看 bigInt 的类型。要注意的是虽然 Number 和 BigInt 都代表的是数字,但是两者是不能混用的,你不能将一个 Number 和一个 BigInt 相加。这会报 TypeError 异常。

如果非要进行操作,那么可以使用 BigInt 构造函数将 Number 转换成为 BigInt 之后再进行。

matchAll()

正则表达式的匹配是一个非常常见的操作,通常我们使用 regExp.exec 来进行正则的匹配,举个正则匹配的例子如下:

const regExp = /yyds(\d+)/g;const text = 'yyds1 is a very good yyds2';let matches;
while ((matches = regExp.exec(text)) !== null) { console.log(matches);}
复制代码

上面的代码运行结果如下:

["yyds1","1"]["yyds2","2"]

复制代码

我们得到了所有匹配的值。不过需要使用一个循环来进行遍历,使用起来有诸多的不便,为了简单起见,ES11 引入了 matchAll()方法。这个方法可以简单的返回一个遍历器,通过遍历这个遍历器,就可以得到所有的匹配的值,如下所示:

const regExp = /yyds(\d+)/g;const text = 'yyds1 is a very good yyds2';let matches = [...text.matchAll(regExp)];
for (const match of matches) { console.log(match);}
复制代码

globalThis

对于 javascript 来说,不同的环境对应的全局对象的获取方式也是不同的,对于浏览器来说通常使用的是 window,但是在 web worker 中使用的是 self,而在 nodejs 中使用的是 global。

为了解决在不同环境中的全局对象不同的问题,ES11 引入了 globalThis,通过这个全局对象,程序员就不用再去区分到底是在哪个环境下了,只需要使用 globalThis 即可。

Promise.allSettled()

自从 Promise 引入之后,有两个方法可以对 Promise 进行组合,分别是 Promise.all() 和 Promise.race(), 他们分别表示返回所有的 Promise 和返回最快的那个。

对于 Promise.all()来说,它会等待所有的 Promise 都运行完毕之后返回,如果其中有一个 Promise 被 rejected,那么整个 Promise.all()都会被 rejected。在这种情况下,如果有一个 Promise 被 rejected,其他的 Promise 的结果也都获取不了。

为了解决这个问题,ES11 引入了 Promise.allSettled() 方法,这个方法会等待所有的 Promise 结束,不管他们是否被 rejected,所以可以使用下面的代码获得所有的结果,而不管其中是否有 Promise 出现问题。

const promises = [promise1("/do1"), promise2("/do2")];const allResults = await Promise.allSettled(promises);const errors = results  .filter(p => p.status === 'rejected')  .map(p => p.reason);
复制代码

??操作符

??操作符是一个判断是否为空然后赋值的操作,如果没有这个操作符,我们通常使用||来简单的进行这个操作,如下所示:

const yourAge = someBody.age || 18
复制代码

上面的代码意思是如果 someBody.age 是空,那么就将 yourAge 设置成为 18。

但是上面代码有个问题,如果 someBody.age=0 的话,上述逻辑也成立。使用??操作符可以解决这个问题。

const yourAge = someBody.age ?? 18
复制代码

?.操作符

我们有时候在获取某个对象的属性的时候,需要进行对象的 null 判断,否则从 null 对象中取出属性就会报错,但是通常的?:操作符使用起来太复杂了,如果有多个对象和属性连写的情况下更是如此,如果使用?.操作符就会简单很多:

const age = school?.class?.student?.age;
复制代码

如上所示,这个一个非常复杂的连写操作,但是使用?.就变得很简单。

同样?.还可以用在对象的方法上:

const age = student.getAge?.();

复制代码

上面代码表示,如果 student 的 getAge 方法存在,则调用,否则返回 undefined。

总结

事实上所有的现代浏览器基本上都支持 ES11 了,IE 除外。大家可以尽情尝试 ES11 的新特征。

本文已收录于 http://www.flydean.com/ecmascript-11/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2 小时前阅读数: 3
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
ECMAScript 2020(ES11)新特性简介