10
votes

Consider this condition:

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

As you can see, the bitwise AND behavior is exactly like logical AND's:

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

I'm wondering why I should use logical operations when the bitwise operations do the same as the logical ones.

Note: Please don't answer that's because of performance issue because it's pretty much faster in Mozilla Firefox, see this jsPerf: http://jsperf.com/bitwise-logical-and

11
in the second example, I think if the first value was false, the rest of the values are not evaluated, because the statement can`t be true.最白目
Your performance test is flawed. You only test with true and false value. The performance problem will kick in when you replace with real function.nhahtdh
If memory serves, & keeps evaluating all the options while && stops at the first false, thus not evaluating the other conditions.npinti
Your first snippet remains valid if you replace & with + or *. That doesn't mean + or * always do the same as the boolean &&.georg
Bitwise operations on one bit are a bit too much ;)Caspar Kleijne

11 Answers

22
votes

The most common use of short-circuit evaluations using logical operators isn't performance but avoiding errors. See this :

if (a && a.length)

You can't simply use & here.

Note that using & instead of && can't be done when you don't deal with booleans. For example & on 2 (01 in binary) and 4 (10 in binary) is 0.

Note also that, apart in if tests, && (just like ||) is also used because it returns one of the operands :

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

More generally, using & in place of && is often possible. Just like omitting most ; in your javascript code. But it will force you to think more than necessary (or will bring you weird bugs from time to time).

13
votes

bitwise operations behavior the same?

No, it's not. Bitwise operators work on integer numbers, while the logical operators have stronlgy different semantics. Only when using pure booleans, the result may be similar.

  • Bitwise operators: Evalutate both operands, convert to 32-bit integer, operate on them, and return the number.
  • Logical operators: Evaluate the first operand, if it is truthy/falsy then evalutate and return second operand else return the first result. This is called Short-circuit evaluation

You already can see this difference in the type of the result:

(true & true & false & false & true) === 0
(true && true && false && false && true) === false
9
votes

No they don't do the same. The differences are:

  1. Whether the operand types are converted
  2. Whether both operands are evaluated
  3. The return value
// sample functions 
function a() { console.log("a()"); return false; }
function b() { console.log("b()"); return true; }

&& (Logical AND)

  1. Checks the truthiness of operands
  2. Uses short-circuiting and may not evaluate the second operand
  3. Returns the last evaluated operand without type conversion
a() && b();
// LOG: "a()"
// RET: false

& (Bitwise AND)

  1. Temporarily converts the operands to their 32bit integer representation (if necessary)
  2. Evaluates both operands
  3. Returns a number
a() & b();
// LOG: "a()"
// LOG: "b()"
// RET: 0
3
votes

Because using && or & convey different intents.

The first says you're testing truthiness.

The second means your conjuring up some bit magic. In real code, you will be looking at variable1 & variable2. It will not be clear that you're in fact intending to test for truth (not truthiness). The reader of the code will probably be confused because it's not obvious why & was used.

Furthermore, the semantics are completely different when taking into account other values than bools and function calls, as pointed out by numerous other posts.

3
votes

Almost everything is already said, but just for completeness' sake I want to take a look at the performance aspect (which you said doesn't matter, but it very well might):

JavaScript has a lot of difficult-to-remember rules on how to evaluate expressions. This includes a lot of type casting (implicit type coercion) when it comes to more complex comparisons. Arrays and Objects need to be converted by calling their toString() methods and are then cast to numbers. This results in a huge performance hit.

The logical operator && is short-circuiting. This means as soon as it encounters a falsy value, the evaluation stops and false is returned. The bitwise operator will always evaluate the entire statement.

Consider the following (yes, quite extreme) short circuit example when very expensive operations (casting an array and an object) are involved: ( performance according to https://jsbench.me in Chromium 90)

// logical operator
( false && {} && [] ) == true
//  /\ short circuits here
// performance: 805M ops/sec  

// bitwise operator
( false  & {}  & [] ) == true // evaluates the entire statement
// performance: 3.7M ops/sec

You can see that the performance differs by a factor of 100!

2
votes
  1. Boolean allows short-circuiting, which can be a performance boost or safety check.
  2. Non-boolean values used in the conditional. For example, if ( 1 & 2 ) will return false, whereas if ( 1 && 2 ) will return true.
1
votes

You can't short-circuit bitwise operators. Also the bitwise operators can do much more, not just compute a boolean expression.

1
votes

There's a huge difference: logical operations are short circuited. It means that (true && true && false ) is the last thing to be executed. This allows powerful constructs, such as abstract factory model using var myFunc = mozilla.func || opera.sameFunc || webkit.evenOneMoreVariationOfTheSameConcept;

All subexpressions of bitwise operations have to be fully evaluated -- and btw. one only rarely needs to evaluate constant bitwise or logical expressions anyway.

1
votes

First condition have to convert first and sum bits then. But second will check logical and return value.

So First one will be slower than second one.

Run This Test: http://jsperf.com/bitwise-logical

on Chrome & IE Bitwise is slower but on FireFox logical is slower

0
votes

Bitwise operators (& and |) converts the two operands to 32 bit "integers" and return the bit operation as a result. The conversion of an operand is 0 if it is not numeric.

The logical operators (&& and ||) are not logical at all, but rather are selectors of one of the operands or 0.

  • The logical && returns the first operand if both exist, otherwise 0
  • The logical || returns the first existing operand, otherwise 0
  • An operand exists if not: undefined, null, false, or 0
-1
votes
var bit1 = (((true & true) & (false & false)) & true), // return 0;
    bit2 = (((true && true) && (false && false)) && true); // return flase

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