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

为什么我喜欢JavaScript的可选链接

时间:2023-03-13 22:18:28 科技观察

JavaScript的一项功能,它可以显着改变您的编码方式。自ES2015以来,对我的代码影响最大的特性是解构、箭头函数、类和模块系统。截至2019年8月,一项名为可选链的新提案已进入第3阶段,这将是一个不错的改进。可选链接改变了从深层对象结构访问属性的方式。让我们看看可选链接如何在深入访问可能缺失的属性时通过删除样板条件和变量来简化代码。1.问题由于JavaScript的动态特性,对象可以有非常不同的嵌套对象结构。通常,您在以下情况下处理此类对象:获取远程JSON数据使用配置对象具有可选属性虽然这为对象提供了支持不同结构数据的灵活性,但在访问这些对象的属性时增加了复杂性。bigObject在运行时可以有不同的属性集://OneversionofbigObjectconstbigObject={//...prop1:{//...prop2:{//...value:'Somevalue'}}};//OtherversionofbigObjectconstbigObject={///...prop1:{//这里什么都没有}};因此,您必须手动检查属性是否存在://Laterif(bigObject&&bigObject.prop1!=null&&bigObject.prop1.prop2!=null){letresult=bigObject.prop1.prop2.value;}这会创建大量样板代码。如果我不必编写这段代码就好了。让我们看看可选链如何解决这个问题并减少样板条件。2.轻松深入访问属性让我们设计一个保存电影信息的对象。该对象包含一个标题属性,以及可选的导演和演员。movieSmall对象仅包含标题,而movieFull包含完整的属性集:constmovieSmall={title:'Heat'};constmovieFull={title:'BladeRunner',director:{name:'RidleyScott'},actors:[{name:'HarrisonFord'},{name:'RutgerHauer'}]};让我们编写一个获取导演姓名的函数。请记住,导演属性可能不存在:>'RidleyScott'if(movie.director){...}条件用于验证导演属性是否已定义。如果没有这种预防措施,JavaScript会在访问movieSmall对象导向器时抛出错误TypeError:Cannotreadproperty'name'ofundefined。这是使用新的可选链接功能并删除movie.director的存在验证的正确位置。新版本的getDirector()看起来要短得多:.director?.name你可以找到?.:可选的链接运算符。在movieSmall的情况下,如果缺少属性director。然后movie.director?.name的计算结果为未定义。可选的链接运算符可防止TypeError:Cannotreadproperty'name'ofundefined被抛出。相反,在movieFull的情况下,属性主管可用。movie.director?.name的值为“RidleyScott”。简单来说,代码片段:letname=movie.director?.name;等同于:letname;if(movie.director!=null){name=movie.director.name;}?。通过减少2行代码()函数来简化getDirector。这就是我喜欢可选链的原因。2.1数组项但是可选的链接功能可以做更多。您可以在同一个表达式中使用多个可选的链接运算符。您甚至可以使用它来安全地访问数组项!下一个任务是编写一个函数,返回电影中主角的名字。在movie对象中,actors数组可以为空甚至缺失,因此您必须添加另一个条件:functiongetLeadingActor(movie){if(movie.actors&&movie.actors.length>0){returnmovie.actors[0].name;}}getLeadingActor(movieSmall);//=>undefinedgetLeadingActor(movieFull);//=>'HarrisonFord'if(movie.actors&&movies.actors.length>0){...}条件需要保证演员属性包含在电影中,并且此属性至少有一个演员。这个任务很容易通过使用可选链来解决:functiongetLeadingActor(movie){returnmovie.actors?.[0]?.name;}getLeadingActor(movieSmall);//=>undefinedgetLeadingActor(movieFull);//=>'HarrisonFord'演员?确保演员属性存在。[0]?.确保第一个演员存在于列表中。非常好!3.名为nullishcoalescingoperatorfornullish的新提议建议使用??处理undefined或null,将它们默认为特定值。如果变量未定义或为空,表达式变量??defaultValue的计算结果为defaultValue,否则表达式的计算结果为变量的值。constnoValue=undefined;constvalue='Hello';noValue??'Nothing';//=>'Nothing'值??'Nothing';//=>'Hello'当评估为undefined时,Nullishmerge可以通过默认值来改进可选链。例如,当电影对象中没有演员时,让我们更改getLeading()函数以返回“未知演员”:functiongetLeadingActor(movie){returnmovie.actors?.[0]?.name??'Unknownact??or';}getLeadingActor(movieSmall);//=>'Unknownact??or'getLeadingActor(movieFull);//=>'HarrisonFord'4.可选链接的三种形式可选链接可以使用以下三种形式。第一种形式object?.property用于访问静态属性:constobject=null;object?.property;//=>undefined第二种形式object?.[expression]用于访问动态属性或数组项:constobject=null;constname='property';object?.[name];//=>undefinedconstarray=null;array?.[0];//=>undefined最后第三种形式object?.([arg1,[arg2,...]])执行一个对象方法:constobject=null;object?.method('Somevalue');//=>undefinedifdesiredcreatelong通过组合这些形式的可选链:constvalue=object.maybeUndefinedProp?.maybeNull()?.[propName];当在其leftHandSide?.rightHandSide中遇到无效值时,右访问器的计算将停止。这称为短路。让我们看一个例子:constnothing=null;letindex=0;nothing?.[index++];//=>undefinedindex;//=>0nothing持有一个空值,因此可选链评估为未定义,并跳过正确的访问设备评估。因为索引号不会增加。6.当使用可选链时,一定要抵制使用可选链操作符访问任何类型属性的冲动:这会导致误导性的使用。下一节将描述何时正确使用它。6.1访问可能为空的属性?必须仅在可能为空的属性周围使用:maybeNullish?.prop。在其他情况下,使用旧的属性访问器:.property或[propExpression]。回忆电影对象。查看表达式movie.director?.name,因为director可以未定义,所以在director属性周围使用可选的链接运算符是正确的。相反,使用?没有意义。访问电影标题:movie?.title。电影对象不会无效。//GoodfunctionlogMovie(movie){console.log(movie.director?.name);console.log(movie.title);}//BadfunctionlogMovie(movie){//directorneedsoptionalchainingconsole.log(movie.director.name);//moviedoesn'tneedoptionalchainingconsole.log(movie?.title);}6.2通常有更好的选择以下函数hasPadding()接受具有可选填充属性的样式对象。padding有可选属性left,top,right,bottom。尝试使用下面的可选链接运算符:functionhasPadding({padding}){consttop=padding?.top??0;constright=padding?.right??0;constbottom=padding?.bottom??0;constleft=padding?。left??0;returnleft+top+right+bottom!==0;}hasPadding({color:'black'});//=>falsehasPadding({padding:{left:0}});//=>falsehasPadding({padding:{right:10}});//=>true虽然该函数正确地确定了一个元素是否有填充,但是很难为每个属性使用可选链接。更好的方法是使用对象扩展运算符将填充对象默认为零值:functionhasPadding({padding}){constp={top:0,right:0,bottom:0,left:0,...padding};returnp.top+p.left+p.right+p.bottom!==0;}hasPadding({color:'black'});//=>falsehasPadding({padding:{left:0}});//=>falsehasPadding({padding:{right:10}});//=>true在我看来,这个版本的hasPadding()更容易阅读。7、我为什么喜欢它?我喜欢可选的链接运算符,因为它允许轻松访问嵌套对象的属性。它减少了编写样板以验证访问器链中每个属性访问器上的无效值的工作量。当可选链接与void合并运算符结合使用时,您可以获得更好的结果并且能够更轻松地处理默认值。