当前位置: 首页 > 科技观察

即将发布的 ES2021 中有哪些有趣的功能

时间:2023-03-18 00:08:52 科技观察

即将到来的ES2021有哪些有趣的特性?BriefES2021(ES12)将于2021年年中发布。在本文中,您将了解五个最有趣的函数:String.prototype.replaceAll()、数字分隔符、逻辑赋值运算符、Promise.any()、WeakRef和Finalizers。本文中描述的五个特性目前处于第4阶段。这意味着它们已经完成并将在JavaScript引擎中实现。这意味着您不会浪费时间学习可能永远不会出现的东西。这些功能将很快发布。有兴趣的可以去官方的EcmaTC39GitHub(https://github.com/tc39/proposals)了解更多其他提案。这个Github存储库跟踪所有提案及其当前阶段。String.prototype.replaceAll()以一个小函数replaceAll()开始,它是对JavaScript语言的补充。当你想替换字符串中多次出现的匹配模式时,你目前可以使用replace()方法,但问题是它只替换第一次出现的地方。这并不意味着replace()不能替换所有出现的匹配模式,只是您必须使用正则表达式。如果你能接受就好了。但是对于很多js程序员来说,正则表达式不是他们的东西(其实是懒得学!)。如果你是这样的js程序员,你一定喜欢新的replaceAll()方法。它的工作方式与replace()类似,不同之处在于replaceAll()会替换所有出现的不带正则表达式的模式。replaceAll()也接受正则表达式,因此您可以使用它代替replace()。//声明一个字符串letstr='Therearethosewholikecats,therethowholikewatchingcatsandthereethosewhohavecats.'//用狗替换所有的“猫”:strstr=str.replaceAll('cats','dogs')console.log(str)//输出://'Therearethosewholikedogs,therethosewholikewatchingdogsandtheretosewholikewatchingdogsandthereethosewholikedogs.'//用replace()写:strstr=str.replace(/cats/g,'dogs')console.log(str)//输出:定界符这是JavaScriptES2021的一个非常小的特性,可以让你在处理大量数字时更轻松一些。数字分隔符提供了一种使大数字更易于阅读和使用的简单方法。语法也很简单:一个下划线_。//Numberconstnumwithoutnumberseparator=3685134689//Numberconstnum=3_685_134_689withnumberseparator但数字分隔符只是为了在视觉上提供一些帮助。使用时对值本身没有任何影响。//带有数字分隔符的数字constnum=3_685_134_689//输出:console.log(num)//Output://3685134689逻辑赋值运算符JavaScript允许在布尔上下文中使用逻辑运算符。示例包括在if...else语句和三元运算符中检查true或false。ES2021的逻辑赋值运算符结合了逻辑运算符和赋值表达式(=)。JavaScript中已经有一些赋值运算符,例如:加法赋值(+=)、减法赋值(-=)、乘法赋值(*=)等。支持逻辑运算符&&、||和??([nullcoalescing])在ES2021中添加。////////////////////逻辑和赋值运算符(&&=)///////////////////x&&=y//以上代码等价于:xx=x&&d//或:if(x){x=y}//例1:letx=3lety=0x&&=yconsole.log(x)//输出://0//例子2:letx=0lety=9x&&=yconsole.log(x)//输出://0//例子3:letx=3//Truthyvalue.lety=15//Truthyvalue.x&&=yconsole.log(x)//输出://15////////////////////逻辑或赋值运算符(||=):x||=y//等价于:xx=x||y//或:if(!x){x=y}//例1:letx=3lety=0x||=yconsole.log(x)//输出://3//例2:letx=0lety=9x||=yconsole.log(x)//Output://9//例3:letx=3lety=15x||=yconsole.log(x)//Output://3///////////////////////////空合并赋值运算符(??=)://///////////////////////x??=y//等价于:xx=x??y//或:if(x==null||x==undefined){x=y}//例1:letx=nulllety='Hello'x??=yconsole.log(x)//输出://'Hello'//例2:letx='Jay'lety='Hello'x??=yconsole.log(x)//Output://'Jay'//例3:letx='Jay'lety=nullx??=yconsole.log(x)//Output://'Jay'//例4:letx=undefinedlety='Jock'x??=yconsole.log(x)//Output://'Jock'看看上面的例子。首先x&&=y。仅当x为真时才将y分配给x。接下来是x||=y,仅当x为假时才将y分配给x。如果x为真且y为假,则不会发生赋值。如果x和y都为假,也会发生同样的情况。最后x??=y。仅当x为null或未定义时才将y分配给x。如果x既不是null也不是undefined,或者y是null或undefined,则不会发生赋值。Promise.any()在ES6中引入了Promise.race()和Promise.all()方法,ES2020增加了Promise.allSettled()。ES2021添加了另一种方法来简化Promise处理:Promise.any()。Promise.any()方法接受多个承诺并在其中任何一个实现时返回一个承诺。它返回Promise.any()完成的第一个承诺。如果所有承诺都被拒绝,Promise.any()将返回一个AggregateError以及拒绝的原因。//示例1:全部被完成://创建promises:constpromise1=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('promise1isresolved.')},Math.floor(Math.random()*1000))})constpromise2=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('promise2isresolved.')},Math.floor(Math.random()*1000))})constpromise3=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('promise3isresolved.')},Math.floor(Math.random()*1000))});(asyncfunction(){//AwaittheresultofPromise.any():constresult=awaitPromise.any([promise1,promise2,promise3])console.log(result)//Output://'promise1isresolved.','promise2isresolved.'or'promise3isresolved.'})()//例2:部分完成:constpromise1=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('promise1isresolved.')},Math.floor(Math.random()*1000))})constpromise2=newPromise((resolve,reject)=>{setTimeout(()=>{reject('promise2wasrejected.')},Math.floor(Math.random()*1000))});(asyncfunction(){//AwaittheresultofPromise.any():constresult=awaitPromise.any([promise1,promise2])console.log(result)//Output://'promise1isresolved.'})()//示例3:全部拒绝:constpromise1=newPromise((resolve,reject)=>{setTimeout(()=>{reject('promise1被拒绝了。')},Math.floor(Math.random()*1000))})constpromise2=newPromise((resolve,reject)=>{setTimeout(()=>{reject('promise2wasrejected.')},Math.floor(Math.random()*1000))});(asyncfunction(){//Usetry...catchtocatchtheAggregateError:try{//AwaitthersultofPromise.any():constresult=awaitPromise.any([promise1,promise2])}catch(err){console.log(err.errors)//Output://['promise1wasrejected.','promise2wasrejected.']}})()弱参考:WeakRef最后一个让人眼前一亮的功能是JavaScript中的WeakRefs。当你创建一个引用来创建一个对象时,这个引用可以防止该对象被gc回收,这意味着JavaScript无法删除该对象并释放其内存。只要对它的引用持续存在,您就可以使对象永远存在。ES2021引入了一个新类WeakRefs。允许创建对对象的弱引用。这可以在不阻止它们被垃圾收集的情况下跟踪现有对象。对于缓存和对象映射非常有用。必须使用new关键字创建一个新的WeakRef,并将某个对象作为参数括在括号中。当你想读取一个引用(被引用的对象)时,你可以通过在弱引用上调用deref()来实现。下面是一个非常简单的例子。constmyWeakRef=newWeakRef({name:'Cache',size:'unlimited'})console.log(myWeakRef.deref())//输出://{name:'Cache',size:'unlimited'}console.log(myWeakRef.deref().name)//Output://'Cache'console.log(myWeakRef.deref().size)//Output://'unlimited'Finalizers和FinalizationRegistry与WeakRef紧密相连的一个名为的函数终结器或FinalizationRegistry。此功能允许您注册一个回调函数,该函数将在对象被gc回收时调用。//创建一个FinalizationRegistry:constreg=newFinalizationRegistry((val)=>{console.log(val)});(()=>{//创建一个新对象:constobj={}//为“obj"object://第一个参数:注册终结器的对象//第二个参数:上面定义的回调函数的值reg.register(obj,'objhasbeengarbage-collected.')})()//当"obj"被GC回收时输出://'objhasbeengarbage-collected.'官方建议不要轻易使用Wea??kRef和finalizer。这样做的一个原因是它们可能是不可预测的,另一个原因是它们并没有真正帮助GC的工作,实际上可能会使GC的工作更加困难。您可以在其提案(https://github.com/tc39/proposal-weakrefs#a-note-of-caution)中阅读更多有关原因的信息。总结ES2021与之前的JavaScript规范如ES6和ES2020相比,看起来更新并不多,但这些有趣的特性值得我们关注。