七大新特性【.com原稿】前言ES2020是ECMAScript对应2020的版本,这个版本没有ES6(ES2015)那么多的新特性。但它也增加了很多有趣和有用的功能。本文以简单的代码示例介绍ES2020的新特性。这样,您无需复杂的解释即可快速了解这些新功能。可选链接操作符(OptionalChaining)可选链接允许我们在查询多层次对象时消除冗余预检查的需要。在日常开发中,当你需要访问对象内部多层嵌套的属性时,可能会遇到臭名昭著的错误UncaughtTypeError:Cannotreadproperty...,这种错误会让整个程序停止。因此,你必须修改你的代码来处理属性链中每一个可能的未定义对象,例如:letnestedProp=obj&&obj.first&&obj.first.second;在访问obj.first.second之前,首先要确认obj和obj.first的值不为null(也不是undefined)。通过可选的链式调用,可以大大简化类似繁琐的预验证操作,而且更安全:letnestedProp=obj?.first?.second;如果obj或obj.first为null/undefined,表达式将被短路计算直接返回undefined。支持可选的链运算符:NullishcoalescingOperator我们在查询一个属性的时候,往往会为没有它的属性设置一个默认值,比如下面两种方法:letc=a?a:b//方法1letc=a||b//方法2这两种方法都有明显的缺点,它们会覆盖所有的假值,比如(0,'',false),这些值可能在某些有效输入的情况下。letx={profile:{name:'boatinthewaves',age:''}}console.log(x.profile.age||18)//18上例中age的属性为空字符串,但它相当于一个假值。为了解决这个问题,ES2020有了一个新特性——空间合并运算符,用??表示。如果表达式在??的左侧求值为未定义或null运算符,返回右侧的默认值。letc=a??b;//等价于letc=a!==undefined&&a!==null?a:b;比如下面的代码:constx=null;consty=x??500;console.log(y);//500constn=0constm=n??9000;console.log(m)//支持0-space合并操作符:Promise.allSettled我们知道Promise.all具有并发执行异步任务的能力。但它最大的问题是,如果参数中的任何promise被rejected,整个Promise.all的调用会立即终止,并返回一个新的拒绝的Promise对象。constpromises=[Promise.resolve(1),Promise.resolve(2),Promise.reject('error')];Promise.all(promises).then(responses=>console.log(responses)).catch(e=>console.log(e))//"error"如果有这样一种场景:一个页面有三个区域,对应三个独立的接口数据,使用Promise.all并发请求三个接口,如果有一个接口是异常,状态为reject,会导致页面三个区域的数据全部出不来。我们不能接受这种情况。Promise.allSettled的出现可以解决这个痛点:Promise.allSettled([Promise.reject({code:500,msg:'serviceexception'}),Promise.resolve({code:200,list:[]}),Promise.resolve({code:200,list:[]})]).then(res=>{console.log(res)/*0:{status:"rejected",reason:{...}}1:{status:"fulfilled",value:{...}}2:{status:"fulfilled",value:{...}}*///过滤掉rejected状态,尽量保证页面区域数据呈现RenderContent(res.filter(el=>{returnel.status!=='returned'}))})Promise。allSettled类似于Promise.all。它的参数接受一个Promise数组并返回一个新的Promise。唯一的区别是它不会短路。也就是说,当所有的Promise都处理完后,我们就可以得到每一个Promise的值了。状态,无论处理是否成功。Promise.allSettled的支持:String.prototype.matchAll如果一个正则表达式在字符串中有多个匹配项,现在一般使用g修饰符或者y修饰符,在循环中一个一个取出来。函数collectGroup1(regExp,str){constmatches=[]while(true){constmatch=regExp.exec(str)if(match===null)breakmatches.push(match[1])}returnmatches}console.log(collectGroup1(/"([^"]*)"/g,`"foo"and"bar"and"baz"`))//['foo','bar','baz']值得注意的是如果如果没有修饰符/g,.exec()只返回第一个匹配。现在通过String.prototype.matchAll方法,可以一次检索所有匹配functioncollectGroup1(regExp,str){letresults=[]for(constmatchofstr.matchAll(regExp)){results.push(match[1])}returnresults}console.log(collectGroup1(/"([^"]*)"/g,`"foo"and"bar"and"baz"`))//["foo","bar","baz"]在上面的代码中,由于string.matchAll(regex)返回一个迭代器,因此可以使用for...of循环检索它。支持String.prototype.matchAll:动态导入现在前端封装资源越来越大。不需要在前端应用程序初始化时加载所有这些逻辑资源。为了更快地渲染首屏,通常会导入动态(按需加载)模块,例如延迟加载图像等,这可以帮助您提高应用程序的性能。这些按需加载的逻辑资源一般都是在事件回调中执行:el.onclick=()=>{import('/modules/my-module.js').then(module=>{//Dosomethingwiththemodule.})。catch(err=>{//loaderror;})}import()可以在脚本中使用,import(module)函数可以在任何地方调用。它返回解析为模块对象的承诺。这种用法还支持await关键字。letmodule=awaitimport('/modules/my-module.js');通过动态导入代码,您可以减少应用程序加载和尽快返回给用户的时间。动态导入支持:BigIntjavascript在Math上一直不好的原因之一是它只能安全??地表示-(2^53-1)到2^53-1范围内的值,即Number.MIN_SAFE_INTEGER到Number.MAX_SAFE_INTEGER,超出此范围的整数计算或表示会失去精度。varnum=Number.MAX_SAFE_INTEGER;//->9007199254740991num=num+1;//->9007199254740992//再次加+1后无法正常运算num=num+1;//->9007199254740992//两个不同的值,但是返回true9007199254740992===9007199254740993//->true所以BigInt应运而生。它是第七种原始类型,可以安全地执行大整数计算。您可以在BigInt上使用与普通数字相同的运算符,例如+、-、/、*、%等。创建BigInt类型的值也非常简单,只需在数字后添加n即可。例如,123变为123n。也可以使用全局方法BigInt(value)进行转换,输入参数值为一个数字或一串数字。constaNumber=111;constaBigInt=BigInt(aNumber);aBigInt===111n//truetypeofaBigInt==='bigint'//truetypeof111//"number"typeof111n//"bigint"只要在后面加上n就可以了数尾计算大数:1234567890123456789n*123n;//->151851850485185185047n但是有个问题,在大多数运算中,BigInt和Number是不能混用的。可以比较Numbers和BigInts,但不能将它们相加。1n<2//true1n+2//UncaughtTypeError:CannotmixBigInandothertypes,useexplicitconversionsBigIntsupport:globalThisglobalThis是获取全局this的新标准方法。以往,开发者会通过以下方式获取:全局变量window:这是一种经典的获取全局对象的方式。但它不适用于Node.js和WebWorkers中的全局变量self:它通常只适用于WebWorkers和浏览器。但它不支持Node.js。有些人会通过判断self是否存在来判断代码是否运行在WebWorkers和浏览器中全局变量global:只在Node.js中有效以前可以通过一个全局函数获取全局对象://ES10之前的解决方案constgetGlobal=function(){if(typeofself!=='undefined')returnsselfif(typeofwindow!=='undefined')returnwindowif(typeofglobal!=='undefined')returnglobalthrownewError('unabletolocateglobalobject')}//ES10内置globalThis.Array(0,1,2)//[0,1,2]//定义一个全局对象v={value:true},ES10是这样定义globalThis.v={value:true}的globalThis的目的是提供一种访问全局对象的标准化方式,有了globalThis,你可以在任何上下文中随时获取全局对象。如果您在浏览器上,globalThis将是窗口,如果您在Node上,globalThis将是全局的。因此,不再需要考虑不同的环境问题。//worker.jsglobalThis===self//node.jsglobalThis===global//browser.jsglobalThis===window新提案还规定Object.prototype必须在全局对象的原型链中。以下代码在最新的浏览器中已经返回true:Object.prototype.isPrototypeOf(globalThis);//对trueglobalThis的支持:参考文章TC39ProposalsMDN文档SeedingES2020NewFeaturesES2020FeaturesinsimpleexamplesNewFeaturesInES2020YouShouldCheck5ECMAScriptProposalsToLookOutInES2020关于作者:乘风破浪:研究生,专注于前端。个人公众号:《前端工匠》,致力于打造一系列适合初中级工程师快速吸收的优质文章!【原创稿件,合作网站转载请注明原作者和出处为.com】
