介绍ES11是ECMA协会在2020年6月发布的一个版本,因为是ECMAScript的第十一个版本,所以也被称为ES11。今天我们就来讲解一下ES11的新特性。ES11引入了9个新特性,接下来我们将一一讲解。动态导入在ES11之前,我们可以使用以下方法导入模块:import*asTestModulefrom"./test-module.js";但是上面的导入方式会存在一些问题,首先是效率的问题,所有的模块在第一次加载的时候都需要导入,这样会降低程序的效率。另外,上述模块名称是硬编码的,不能在程序运行时动态修改。也就是说,上面的模块导入方式不能动态导入模块,也不能按需导入,使用上有很多不便。为了解决这个问题,ES11引入了一个新的import()方法。使用该方法,可以动态导入模块,通过设置模块名变量,可以动态修改模块名,非常神奇。我们来看一个具体的用法示例:constbaseModulePath="./baseModules";constbtnImportModule=document.getElementById("btnImportModule");letuserList=[];btnImportModule.addEventListener("click",asynce=>{constuserModule=awaitimport(`${baseModulePath}/users.js`);userList=userModule.getUsers();});在上面的代码中,我们定义了一个基本的Module路径,可以通过点击页面上的按钮动态加载一个users.js模块,然后调用该模块的getUsers()方法获取userList列表。import.meta除了动态导入模块外,import还提供了一个meta属性meta,包含了当前导入模块的信息。目前里面有一个url属性,代表了模块被引用的URL。如果要使用URL信息,可以在代码中使用import.meta.url。ECMAScript2015引入了exportenhancedimport,主要用于引入模块。import可以导入整个模块,也可以导入部分模块。如下图:import{something}from"./test-module.js";import*from"./test-module.js";而import对应export,也可以导出全部或部分,如下图:export{something}from"./test-module.js";export*from"./test-module.js";一般来说,上面说的import和export就够了,但是对于export模块,需要在重做命名的情况下,我们不能直接export,而是必须在import的时候先rename,然后再用export将改名后的模块导出:import*asmyModulefrom"./test-module.js";export{myModule};如果使用了export的增强,则不需要使用import,直接使用export即可导出:export*as{myModule}from"./test-module.js";BigIntES11引入了一种新的数据类型BigInt,在此之前,javascript中表示数字的对象是Number,可以表示64位浮点数。当然也可以表示整数,但是整数表示的最大值是2^53,也可以用Number.MAX_SAFE_INTEGER来表示。一般来说,Number就够了,但是如果在某些情况下需要存储或操作64位的整数,或者要表示的范围超过64位,Number就不够用了。怎么做?如果只是存储,可以存储为字符串,但是第二个字符串不适用。于是引入BigInt来解决这个问题。要表示BigInt,只需在数字后添加n。constbigInt=112233445566778899n;或者使用构造函数构造bigInt:constbigInt=BigInt("112233445566778899");可以使用typeof查看bigInt的类型。需要注意的是,虽然Number和BigInt都表示数字,但是两者不能混用。您不能添加Number和BigInt。这样会报TypeError异常。如果一定要操作,可以使用BigInt构造函数将Number转换为BigInt后再进行操作。matchAll()正则表达式匹配是一个很常见的操作。通常我们使用regExp.exec来进行正则匹配。正则匹配的例子如下:constregExp=/yyds(\d+)/g;consttext='yyds1isaverygoodyyds2';letmatches;while((matches=regExp.exec(text))!==null){console.log(matches);}上面代码的结果如下:["yyds1","1"]["yyds2","2"]我们得到所有匹配值。但是需要用循环遍历,使用起来不方便。为了简单起见,ES11引入了matchAll()方法。该方法可以简单的返回一个遍历器,通过遍历遍历器,可以得到所有匹配的值,如下所示:constregExp=/yyds(\d+)/g;consttext='yyds1isaverygoodyyds2';letmatches=[...text.matchAll(regExp)];for(constmatchofmatches){console.log(match);}globalThis对于javascript,如何获取不同环境对应的全局对象也是不同的。对于浏览器,通常使用window,但是在webworker中使用self,在nodejs中使用global。为了解决不同环境下全局对象不同的问题,ES11引入了globalThis。通过这个全局对象,程序员不再需要区分自己处于哪个环境,只需要使用globalThis即可。Promise.allSettled()自从Promise的引入,有两个方法结合Promise,分别是Promise.all()和Promise.race(),分别代表返回所有Promise和最快的一个。对于Promise.all(),它等待所有Promise完成运行并返回。如果其中一个Promise被拒绝,整个Promise.all()将被拒绝。在这种情况下,如果一个Promise被拒绝,则无法获取其他Promise的结果。为了解决这个问题,ES11引入了Promise.allSettled()方法,该方法会等待所有的Promise结束,不管是否被拒绝,所以可以使用下面的代码获取所有的结果,不管是否有是Promise的问题。constpromises=[promise1("/do1"),promise2("/do2")];constallResults=awaitPromise.allSettled(promises);consterrors=results.filter(p=>p.status==='rejected').map(p=>p.reason);??操作员??运算符是判断是否为空然后赋值的操作。如果没有这个运算符,我们通常使用||简单地执行此操作。如下:constyourAge=someBody.age||18上面代码的意思是如果someBody.age为空,那么把yourAge设置为18。但是上面的代码有个问题,如果someBody.age=0,上面的逻辑也是成立的。使用??运营商可以解决这个问题。constyourAge=someBody.年龄??18?运算符有时候我们在获取一个对象的属性的时候,需要判断对象的null,否则从null对象中取出属性的时候会报错,但是通常的?:运算符使用起来太复杂了,if当有多个对象和属性时尤其如此。如果您使用?.运算符,它会简单得多:constage=school?.class?.student?.age;如上所示,这是一个非常复杂的操作,但是使用?。让它变得容易。相同?。也可以用在对象方法中:constage=student.getAge?.();上面代码表示如果学生的getAge方法存在,则调用它,否则返回undefined。总结其实现代浏览器基本都支持ES11,除了IE。你可以试试ES11的新特性。本文已收录于http://www.flydean.com/ecmascript-11/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!
