三元运算符中误用按位与(&)却正常运行的原理问询
为什么用按位与
&代替逻辑与&&代码还能正常运行? 先把核心概念掰明白:
&&是逻辑与运算符,专门用来做条件判断,具备短路特性(左边表达式为假时,右边表达式不会执行),返回的是真值或假值。&是按位与运算符,原本的作用是对两个数字的二进制位做逐位运算,运算前会把所有操作数转成32位整数,返回结果是数字。
你的代码里&能“蒙混过关”的原因
1. 三元运算符里的sortedArray.push(...) & leftArray.shift()
JS计算表达式时,会先把&两边的操作数全部执行完毕,再进行按位与运算。所以不管最终按位与的结果是什么,你需要的两个核心操作——push添加元素、shift移除数组头部——都会被依次执行。
push返回数组的新长度(必然是正数,属于真值)shift返回被移除的元素(如果是数字数组就是数字)
你根本没用到按位与的结果,只是蹭了“先执行两边表达式”这个副作用,所以代码看起来正常工作了。
2. while循环条件里的leftArray.length > 0 & rightArray.length > 0
length > 0返回的是布尔值,JS会自动把布尔值转成数字:true转为1,false转为0。
- 当两个数组都有元素时,
1 & 1 = 1,非0数字在条件判断里会被识别为true,循环继续。 - 当任意一个数组为空时,
1 & 0 = 0或0 & 0 = 0,0会被识别为false,循环终止。
这里也能达到和&&一样的效果,但&没有短路特性——哪怕左边数组已经空了,右边的rightArray.length > 0还是会被计算一遍(虽然这里不影响功能,但完全不符合逻辑判断的语义)。
但这绝对是错误的写法!
别因为代码能跑就这么用,理由很直接:
- 可读性极差:谁看到
&会想到你是要连续执行两个操作?别人只会以为你在做位运算,完全摸不着头脑。 - 存在潜在bug:如果数组里不是数字(比如字符串),
shift返回的字符串转成数字会变成NaN,NaN和任何数按位与的结果都是0,要是后续代码不小心用到这个结果,直接出问题。 - 不符合最佳实践:要在一行执行多个操作,正确的姿势是用逗号运算符,它的语义就是依次执行多个表达式,返回最后一个表达式的结果:
leftArray[0] < rightArray[0] ? (sortedArray.push(leftArray[0]), leftArray.shift()) : (sortedArray.push(rightArray[0]), rightArray.shift())
或者用&&也可以(因为push返回的数组长度永远是真值,右边的shift一定会执行):
leftArray[0] < rightArray[0] ? sortedArray.push(leftArray[0]) && leftArray.shift() : sortedArray.push(rightArray[0]) && rightArray.shift()
至于while循环的条件,必须换回&&,这才是逻辑判断该用的运算符:
while (leftArray.length > 0 && rightArray.length > 0)
内容的提问来源于stack exchange,提问作者Sergio Ruiz Sánchez
相关产品推荐
相关产品推荐

