繁体   English   中英

当按位运算符执行相同操作时,为什么要使用逻辑运算符?

[英]Why use logical operators when bitwise operators do the same?

考虑这个条件:

(true & true & false & false & true) == true //returns: false

如您所见,按位 AND 行为与逻辑 AND 完全一样:

(true && true && false && false && true) == true //returns: false

我想知道为什么当按位运算与逻辑运算相同时我应该使用逻辑运算。

注意:请不要回答这是因为性能问题,因为它在 Mozilla Firefox 中要快得多,请参阅此 jsPerf: http ://jsperf.com/bitwise-logical-and

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

if (a && a.length)

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

请注意,当您不处理布尔值时,无法使用&而不是&& 例如&2 (二进制中的01 )和4 (二进制中的10 )上是0

还要注意的是,除了在if测试中, && (就像|| )也被使用,因为它返回操作数之一

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

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

按位运算行为相同吗?

不,这不对。 按位运算符处理整数,而逻辑运算符具有不同的语义。 仅当使用纯布尔值时,结果可能相似。

  • 按位运算符:计算两个操作数,转换为 32 位整数,对它们进行运算,并返回数字。
  • 逻辑运算符:评估第一个操作数,如果它是真/假,则评估并返回第二个操作数,否则返回第一个结果。 这称为短路评估

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

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

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

  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

因为使用&&&传达不同的意图。

第一个说你正在测试真实性

第二个意味着你变出一些魔法。 在实际代码中,您将查看variable1 & variable2 不会是清楚你实际上打算测试真理(感实性)。 代码的读者可能会感到困惑,因为使用&原因并不明显。

此外,正如许多其他帖子所指出的那样,在考虑 bool 和函数调用以外的其他值时,语义完全不同。

几乎所有内容都已经说过了,但为了完整起见,我想看看性能方面(您说的无关紧要,但很可能):

JavaScript 有很多关于如何计算表达式的难以记住的规则。 当涉及到更复杂的比较时,这包括很多类型转换(隐式类型强制)。 数组和对象需要通过调用它们的toString()方法进行转换,然后转换为数字。 这会导致巨大的性能损失。

逻辑运算符&&是短路的。 这意味着一旦遇到值,评估就会停止并返回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. Boolean 允许短路,这可以是性能提升或安全检查。
  2. 条件中使用的非布尔值。 例如, if ( 1 & 2 )将返回 false,而if ( 1 && 2 )将返回 true。

您不能短路按位运算符。 此外,按位运算符可以做更多的事情,而不仅仅是计算布尔表达式。

有一个巨大的区别:逻辑操作是短路的。 这意味着 (true && true && false ) 是最后要执行的事情。 这允许强大的构造,例如使用var myFunc = mozilla.func || opera.sameFunc || webkit.evenOneMoreVariationOfTheSameConcept;抽象工厂模型var myFunc = mozilla.func || opera.sameFunc || webkit.evenOneMoreVariationOfTheSameConcept;

按位运算的所有子表达式都必须完全计算——顺便说一句。 无论如何,很少需要计算常量按位或逻辑表达式。

第一个条件必须先转换然后求和位。 但是第二个将检查逻辑和返回值。

所以第一个会比第二个慢。

运行此测试: http : //jsperf.com/bitwise-logical

在 Chrome 和 IE 上按位较慢,但在 FireFox 上逻辑较慢

按位运算符(& 和 |)将两个操作数转换为 32 位“整数”并返回位运算结果。 如果操作数不是数字,则其转换为 0。

逻辑运算符(&& 和 ||)根本不符合逻辑,而是操作数之一或 0 的选择器。

  • 如果两者都存在,则逻辑 && 返回第一个操作数,否则返回 0
  • 逻辑 || 返回第一个存在的操作数,否则为 0
  • 如果不存在,则操作数存在:未定义、空、假或 0
var bit1 = (((true & true) & (false & false)) & true), // return 0;
    bit2 = (((true && true) && (false && false)) && true); // return flase

alert(bit1 + ' is not ' + bit2);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM