当按位运算符做同样的事情时,为啥要使用逻辑运算符?
Posted
技术标签:
【中文标题】当按位运算符做同样的事情时,为啥要使用逻辑运算符?【英文标题】:Why use logical operators when bitwise operators do the same?当按位运算符做同样的事情时,为什么要使用逻辑运算符? 【发布时间】:2013-01-30 00:46:13 【问题描述】:考虑这种情况:
(true & true & false & false & true) == true //returns: false
如您所见,按位与行为与逻辑与完全一样:
(true && true && false && false && true) == true //returns: false
我想知道为什么当按位运算与逻辑运算相同时,我应该使用逻辑运算。
注意:请不要因为性能问题而回答,因为它在 Mozilla Firefox 中要快得多,请参阅这个 jsPerf:http://jsperf.com/bitwise-logical-and
【问题讨论】:
在第二个例子中,我认为如果第一个值为 false,则不会评估其余值,因为该语句不能为 true。 您的性能测试有缺陷。您仅使用true
和 false
值进行测试。当你用真正的函数替换时,性能问题就会出现。
如果有记忆,&
会继续评估所有选项,而&&
会在第一个false
处停止,因此不会评估其他条件。
如果您将&
替换为+
或*
,您的第一个sn-p 仍然有效。这并不意味着 +
或 *
总是 与布尔值 &&
一样。
对一位的按位运算有点太多了;)
【参考方案1】:
使用逻辑运算符的短路评估最常见的用途不是性能,而是避免错误。看到这个:
if (a && a.length)
你不能在这里简单地使用&
。
请注意,当您不处理布尔值时,无法使用&
而不是&&
。例如&
上的2
(01
二进制)和4
(10
二进制)是0
。
还要注意,除了在if
测试中,&&
(就像||
)也被使用,因为it returns one of the operands:
"a" & "b" => 0
"a" && "b" => "b"
更一般地说,通常可以使用&
代替&&
。就像在您的 javascript 代码中省略大多数 ;
一样。但它会迫使你思考多余的东西(或者会不时给你带来奇怪的错误)。
【讨论】:
Lazy evaluation 通常比short-circuit evaluation 具有更广泛/不同的含义。 @phant0m 短路在这里更精确,是的。已更新。【参考方案2】:按位运算的行为是否相同?
不,不是。位运算符适用于整数,而逻辑运算符具有截然不同的语义。只有当使用纯布尔值时,结果可能是相似的。
Bitwise operators:计算两个操作数,转换为 32 位整数,对它们进行运算,然后返回数字。 Logical operators:评估第一个操作数,如果它是真/假,则评估并返回第二个操作数,否则返回第一个结果。这称为Short-circuit evaluation您已经可以看到结果类型的这种差异:
(true & true & false & false & true) === 0
(true && true && false && false && true) === false
【讨论】:
【参考方案3】:不,他们不这样做。区别在于:
-
是否转换操作数类型
是否计算两个操作数
返回值
// sample functions
function a() console.log("a()"); return false;
function b() console.log("b()"); return true;
&&(逻辑与)
-
检查操作数的真实性
使用短路且不能计算第二个操作数
返回最后计算的操作数,不进行类型转换
a() && b();
// LOG: "a()"
// RET: false
&(按位与)
-
临时将操作数转换为其 32 位整数表示(如有必要)
计算两个操作数
返回一个数字
a() & b();
// LOG: "a()"
// LOG: "b()"
// RET: 0
【讨论】:
您的意思可能是“按位与”而不是布尔值。【参考方案4】:因为使用&&
或&
传达不同的意图。
第一个说你正在测试truthiness。
第二个意思是你变了一些魔法。在实际代码中,您将看到variable1 & variable2
。 不很明显,您实际上是打算测试真实性(不是真实性)。代码的读者可能会感到困惑,因为不清楚为什么使用&
。
此外,正如许多其他帖子所指出的那样,考虑到布尔值和函数调用以外的其他值时,语义完全不同。
【讨论】:
你是对的 - 他们采用了“真实和虚假”(我个人的,无关紧要的懊恼;-)),也许你应该链接到一个解释(例如11heavens.com/falsy-and-truthy-in-javascript)。我将删除我原来的 cmets。 @MadKeithV 好主意,完成。那么,我也会删除我之前的 cmets。【参考方案5】:几乎所有内容都已经说了,但为了完整起见,我想看看性能方面(你说的无关紧要,但很有可能):
JavaScript 有很多难以记住的关于如何计算表达式的规则。当涉及到更复杂的比较时,这包括很多类型转换(隐式类型强制)。数组和对象需要通过调用它们的toString()
方法进行转换,然后转换为数字。这会导致巨大的性能损失。
逻辑运算符&&
短路。这意味着一旦遇到falsy 值,评估就会停止并返回false
。位运算符将始终计算整个语句。
当涉及非常昂贵的操作(转换数组和对象)时,请考虑以下(是的,非常极端的)短路示例:(性能根据 Chromium 90 中的https://jsbench.me)
// logical operator
( false && && [] ) == true
// /\ short circuits here
// performance: 805M ops/sec
// bitwise operator
( false & & [] ) == true // evaluates the entire statement
// performance: 3.7M ops/sec
您可以看到性能相差 100 倍!
【讨论】:
+1 不错,但基准测试并没有说性能很重要。在这种情况下,性能主要是红鲱鱼,因为语义完全不同。 语义主题已经被其他答案所覆盖,我只是想指出类型强制导致的性能问题。 您的回答没有说明哪种方式更快,也没有说明您的陈述适用于哪些运营商。 “数组和对象需要通过调用其 toString() 方法进行转换,然后转换为数字”用于逻辑或按位运算符?这个答案对读者只知道你在暗示什么做出了奇怪的假设,因此是不完整的。链接也坏了。 @KyleDelaney 我认为他的意思是两者都必须转换为字符串,然后转换为数字。如果其中一个没有受到影响,那么举一个短路的例子是没有意义的,因为你不知道哪个更快。我很确定他的意思是在这种情况下逻辑更快。 @KyleDelaney 即使你拉了一个不错的死灵(这个帖子已经有 8 年历史了 ;-)),为了清楚起见,我编辑了我的答案。我希望现在我想说的更清楚了?【参考方案6】:-
布尔值允许短路,这可以是性能提升或安全检查。
条件中使用的非布尔值。例如,
if ( 1 & 2 )
将返回 false,而 if ( 1 && 2 )
将返回 true。
【讨论】:
我认为你不明白按位...试试(2&3)?"true":"false"
@Christoph 打扰一下? (2&3)
将是真的,因为它是 0010 & 0011
,即 0010
。另一方面,(1&2)
是 0001 & 0010
,即 0000
。我的观点是,如果您使用按位 &,使用非布尔值可能会得到意想不到的结果。
好的,我撤销了我的声明,但是Non-boolean values used in the conditional if will return false
这句话暗示这适用于所有情况,但事实并非如此。也许您想改写它,以便更清楚您的意思。
@Christoph 我认为您错过了“有条件”之后的时间段,但要点是。 :)【参考方案7】:
您不能短路按位运算符。此外,位运算符可以做更多的事情,而不仅仅是计算布尔表达式。
【讨论】:
【参考方案8】:有一个巨大的区别:逻辑运算是短路的。这意味着 (true && true && false ) 是要执行的最后一件事。这允许强大的构造,例如使用var myFunc = mozilla.func || opera.sameFunc || webkit.evenOneMoreVariationOfTheSameConcept;
的抽象工厂模型
按位运算的所有子表达式都必须完全求值——顺便说一句。无论如何,人们很少需要计算常量位或逻辑表达式。
【讨论】:
【参考方案9】:第一个条件必须先转换然后求和。但是第二个会检查逻辑和返回值。
所以第一个会比第二个慢。
运行此测试:http://jsperf.com/bitwise-logical
在 Chrome 和 IE 上 Bitwise 较慢 但在 FireFox 上逻辑较慢
【讨论】:
对于布尔组合,第一个会更慢是不正确的。&&
添加分支,速度很慢。【参考方案10】:
按位运算符(& 和 |)将两个操作数转换为 32 位“整数”并返回位运算结果。如果操作数不是数字,则转换为 0。
逻辑运算符(&& 和 ||)根本不是逻辑运算符,而是操作数之一或 0 的选择器。
逻辑 && 如果两者都存在则返回第一个操作数,否则返回 0 逻辑 ||返回第一个现有操作数,否则返回 0 如果不存在则操作数存在:未定义、null、false 或 0【讨论】:
【参考方案11】:var bit1 = (((true & true) & (false & false)) & true), // return 0;
bit2 = (((true && true) && (false && false)) && true); // return flase
alert(bit1 + ' is not ' + bit2);
【讨论】:
对不起,我没有找到你,正如@Christoph 之前提到的,0
等于 false
。以上是关于当按位运算符做同样的事情时,为啥要使用逻辑运算符?的主要内容,如果未能解决你的问题,请参考以下文章