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

空合并运算符'--'的操作和应用

时间:2023-03-17 18:45:03 科技观察

null合并运算符(??)是一个逻辑运算符,当左边的操作数为null或undefined时返回其右操作数,否则返回左操作数。与逻辑或运算符(||)不同,逻辑或运算符在左操作数为假时返回右操作数。也就是说,如果你使用||为某些变量设置默认值,您可能会遇到意想不到的行为。比如当false时(例如,''或0)。请参见下面的示例。constfoo=null??'defaultstring';console.log(foo);//expectedoutput:"defaultstring"constbaz=0??42;console.log(baz);//expectedoutput:0syntaxleftExpr??rightExprexampleusingnull值合并运算符在此示例中,我们使用空值合并运算符为常量提供默认值,确保常量不为空或未定义。constnullValue=null;constemptyText="";//空字符串为假值,Boolean("")===falseconstsomeNumber=42;constvalA=nullValue??"valA的默认值";constvalB=emptyText???valB的默认值";constvalC=someNumber??0;console.log(valA);//"valA的默认值"console.log(valB);//""(空字符串虽然是false值,但不是null也不是undefined)console.log(valC);//42在给变量赋默认值之前,如果要赋默认值给一个变量,通常的方式是使用逻辑或操作符(||):letfoo;//fooisneverassignedanyvaluesoitisstillundefinedletsomeDummyText=foo||'Hello!';然而,由于||是布尔逻辑运算符,左操作数被强制转换为布尔值以进行评估。不会返回任何假值(0、''、NaN、null、undefined)。如果您使用0、''或NaN作为有效值,这会导致不可预测的行为。letcount=0;lettext="";letqty=count||42;letmessage=text||"hi!";console.log(qty);//42而不是0console.log(message);//"hi!",而不是"",null合并运算符通过仅在第一个操作数为null或未定义(而不是其他情况下为false)时返回第二个操作数来避免此陷阱:letmyText='';//Anemptystring(whichisalsoafalsyvalue)letnotFalsyText=myText||'Helloworld';console.log(notFalsyText);//HelloworldletpreservingFalsy=myText??'Hineighborhood';console.log(preservingFalsy);//''(asmyTextisneitherundefinednornull)短路与OR类似于AND逻辑运算符,当左侧表达式不为null或undefined时,右侧表达式不被计算。functionA(){console.log('函数A被调用');returnundefined;}functionB(){console.log('函数B被调用');returnfalse;}functionC(){console.log('函数C被称为');return"foo";}console.log(A()??C());//依次打印"函数A被调用","函数C被调用","foo"//A()返回undefined,所以运算符两边的表达式都被执行了norundefined)//所以右边的表达式不执行不能与AND或OR运算符共享使用??直接与AND(&&)和OR(||)运算符组合是不可取的。(译者注:应该是因为空值合并运算符和其他逻辑运算符之间的运算优先级/运算顺序未定义)在这种情况下,会抛出SyntaxError。null||undefined???"foo";//ThrowSyntaxErrortrue||undefined??"foo";//ThrowSyntaxError但是,如果用括号明确表示操作的优先级,是没有问题的:(null||undefined)???"foo";//返回"foo"与可选链运算符(?.)的关系。.)也是这样。可选的链接运算符在访问属性可能未定义和为null的对象时很有用。letfoo={someFooProp:"hi"};console.log(foo.someFooProp?.toUpperCase());//"HI"console.log(foo.someBarProp?.toUpperCase());//未定义