不同于逻辑或运算符(||),当左操作数为假值数时返回右运算。也就是说,如果你使用||为某些变量设置默认值,您可能会遇到意想不到的行为。比如当false时(例如,''或0)。请参见下面的示例。constfoo=null??'默认字符串';console.log(foo);//预期输出:“默认字符串”constbaz=0??42;console.log(baz);//预期输出:0示例用法空合并运算符在本例中,我们使用空合并运算符为常量提供默认值,确保常量不为空或未定义。常量nullValue=null;constemptyText="";//空字符串,是一个假值,Boolean("")===falseconstsomeNumber=42;constvalA=nullValue??“valA的默认值”;constvalB=emptyText??“valB的默认值”;constvalC=someNumber??0;控制台日志(valA);//"valA的默认值"console.log(valB);//""(虽然空字符串是一个假值,但不是null或undefined)console.log(valC);//42在给变量赋默认值之前,如果要给变量赋默认值,通常的做法是使用逻辑或运算符(||):letfoo;//fooisneverassignedanyvalue所以它仍然是未定义的letsomeDummyText=foo||'你好!';然而,由于||是一个布尔运算符,左边的操作数被强制转换为一个布尔值用于评估。不会返回任何假值(0、''、NaN、null、undefined)。如果您使用0、''或NaN作为有效值,这会导致不可预测的行为。letcount=0;lettext="";letqty=count||42;让消息=文本||“嗨!”;console.log(数量);//42而不是0console.log(message);//“你好!”而不是""null合并运算符通过仅在第一个操作数为null或未定义(而不是其他情况下为false)时返回第二个操作数来避免此陷阱:letmyText='';//一个空字符串(也是一个假值)letnotFalsyText=myText||'你好世界';console.log(notFalsyText);//HelloworldletpreservingFalsy=myText??'嗨邻居';console.log(preservingFalsy);//''(因为myText既不是undefined也不是null)短路类似于OR和AND逻辑运算符,当左边的表达式不为null或undefined时,右边的表达式将不会被计算。functionA(){console.log('函数A被调用');返回未定义;}functionB(){console.log('函数B被调用');返回假;}functionC(){console.log('函数C被调用');返回“富”;}console.log(A()??C());//Print"FunctionAiscalled"and"FunctionCiscalled","foo"//A()返回undefined,所以两边的表达式运算符被执行console.log(B()??C());//依次打印“函数B被调用”,“false”//B()返回false(既不是null也不是undefined)//所以右边的表达式不执行,不能与AND或OR运算符一起使用。使用??直接与AND(&&)和OR(||)运算符组合是不可取的。(译者注:应该是因为空值合并运算符和其他逻辑运算符之间的运算优先级/运算顺序未定义)在这种情况下,会抛出SyntaxError。空||不明确的??“富”;//抛出SyntaxErrortrue||不明确的??“富”;//throwsSyntaxError但是,如果你使用括号来显式指示操作的优先级,则没有问题:(null||undefined)??“富”;//return"foo"andtheoptionalchainingoperator(?.)nullcoalescingoperator对于undefined和null这两个值,optionalchainingoperator(?..)也是这样。可选的链接运算符在访问属性可能未定义和为null的对象时很有用。让foo={someFooProp:"hi"};console.log(foo.someFooProp?.toUpperCase());//"嗨"console.log(foo.someBarProp?.toUpperCase());//未定义浏览器兼容性
