【问题标题】: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。
  • 您的性能测试有缺陷。您仅使用 truefalse 值进行测试。当你用真正的函数替换时,性能问题就会出现。
  • 如果有记忆,& 会继续评估所有选项,而&& 会在第一个false 处停止,因此不会评估其他条件。
  • 如果您将& 替换为+*,您的第一个sn-p 仍然有效。这并不意味着 +* 总是 与布尔值 && 一样。
  • 对一位的按位运算有点太多了;)

标签: javascript operators bitwise-operators logical-operators


【解决方案1】:

使用逻辑运算符的短路评估最常见的用途不是性能,而是避免错误。看到这个:

if (a && a.length)

你不能在这里简单地使用&

请注意,当您不处理布尔值时,无法使用& 而不是&&。例如& 上的201 二进制)和410 二进制)是0

还要注意,除了在if 测试中,&&(就像||)也被使用,因为it returns one of the operands

"a" & "b" => 0
"a" && "b" => "b"

更一般地说,通常可以使用& 代替&&。就像在您的 javascript 代码中省略大多数 ; 一样。但它会迫使你思考多余的东西(或者会不时给你带来奇怪的错误)。

【讨论】:

【解决方案2】:

按位运算的行为是否相同?

不,不是。位运算符适用于整数,而逻辑运算符具有截然不同的语义。只有当使用纯布尔值时,结果可能是相似的。

您已经可以看到结果类型的这种差异:

(true & true & false & false & true) === 0
(true && true && false && false && true) === false

【讨论】:

    【解决方案3】:

    不,他们不这样做。区别在于:

    1. 是否转换操作数类型
    2. 是否计算两个操作数
    3. 返回值
    // sample functions 
    function a() { console.log("a()"); return false; }
    function b() { console.log("b()"); return true; }
    

    &&(逻辑与)

    1. 检查操作数的真实性
    2. 使用短路且不能计算第二个操作数
    3. 返回最后计算的操作数,不进行类型转换
    a() && b();
    // LOG: "a()"
    // RET: false
    

    &(按位与)

    1. 临时将操作数转换为其 32 位整数表示(如有必要)
    2. 计算两个操作数
    3. 返回一个数字
    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】:
    1. 布尔值允许短路,这可以是性能提升或安全检查。
    2. 条件中使用的非布尔值。例如,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
          猜你喜欢
          • 1970-01-01
          • 2012-08-10
          • 1970-01-01
          • 1970-01-01
          • 2014-07-01
          • 2012-07-20
          • 2020-01-23
          • 2020-04-07
          • 1970-01-01
          相关资源
          最近更新 更多