Why use logical operators when bitwise operators do the same? - javascript

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

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).

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

No they don't do the same. The differences are:
Whether the operand types are converted
Whether both operands are evaluated
The return value
// sample functions
function a() { console.log("a()"); return false; }
function b() { console.log("b()"); return true; }
&& (Logical AND)
Checks the truthiness of operands
Uses short-circuiting and may not evaluate the second operand
Returns the last evaluated operand without type conversion
a() && b();
// LOG: "a()"
// RET: false
& (Bitwise AND)
Temporarily converts the operands to their 32bit integer representation (if necessary)
Evaluates both operands
Returns a number
a() & b();
// LOG: "a()"
// LOG: "b()"
// RET: 0

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!

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.

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

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

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.

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

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

var bit1 = (((true & true) & (false & false)) & true), // return 0;
bit2 = (((true && true) && (false && false)) && true); // return flase
alert(bit1 + ' is not ' + bit2);

Related

Javascript Simple Boolean Arithemetic

I’ve heard of boolean arithmetic and thought of giving it a try.
alert (true+true===2) //true
alert (true-true===0) //true
So algebra tells me true=1
alert (true===1) //false :O
Could someone explain why this happens?
=== is the strict equality operator. Try == operator instead.
true==1 will evaluate to true.
The strict equality operator === only considers values equal if they
have the same type. The lenient equality operator == tries to
convert values of different types, before comparing like strict
equality.
Case 1:
In case of true===1, The data type of true is boolean whereas the type of 1 is number. Thus the expression true===1 will evaluate to false.
Case 2:
In case of true+true===2 and true-true===0 the arithmetic operation is performed first(Since + operator takes precedence over ===. See Operator Precedence) and then the result is compared with the other operand.
While evaluating expression (true+true===2), the arithmetic operation true+true performed first producing result 2. Then the result is compered with the other operand. i.e. (2==2) will evaluate to true.
Because comparing data TYPE and value (that's what operator '===' does ), TRUE is not exactly the same as 1. If you changed this to TRUE == 1, it should work fine.
At the beginning, you're doing bool + bool. The + operator takes precedence over the === operator so it's evaluated first. In this evaluation, it's converting the booleans to their number forms. Run console.log(true + true); and this will return 2. Since you're comparing the number 2 to the number 2, you get a return value true with the strict equality.
When you're just comparing true === 1, like everyone else said you're comparing the boolean true to the number 1 which is not strictly equal.
first 2 expression are true because you are using expression (true+true) (true-true) it convert type of a value first due to expression and check equality with "===", toNumber and toPrimitive are internal methods which convert their arguments (during expression ) this is how conversion take place during expression
That's why true+true equal to the 2
In your third expression you are using === this not convert arguments just check equality with type, to make it true both values and there type must be same.
Thats all

Bitwise Assignment Operator for Boolean instead of Longer Expression ( |= operator)

Question
A friend of mine is asking whether he could use:
result |= condition
Instead of:
result = result || condition
in javascript, for boolean operations.
I'm well aware that one is bitwise and the other is logical.
However, what would be the effect on boolean variables?
I'm not currently in front of my computer but also wondering if there could be such a thing as a ||= operator.
Update
I just realized that a boolean value is essentialy a 1 bit value. Does this mean that for booleans the logical or has the same as the bitewise or ?
So a|=b would be equivalent to a=a|b ?
Does this mean that for booleans the logical or has the same as the bitewise or ?
In your case, somewhat.
When using logical expressions, operands may either be true-ish or false-ish. An OR-expression here returns the first one that is true-ish (not necessarily the boolean true), or if none is, the last operand.
result || condition
Returns result if result is true-ish, otherwise condition
When using bitwise expressions, operands are signed 32 bit integers. If you limit that to one bit, this somewhat resembles the behaviour of logical expressions: If one bit is set, an OR-expression returns 1.
result | condition
Returns a signed 32 bit integer with a value of 0 or 1 for operands convertible to a 32bit integer with only the least significant bit used.
However, when using bitwise expressions on operands that are not a 32 bit integer, implicit conversions to 32 bit integers have to be performed and there might be additional edge cases. I'd not recommend using bitwise expressions for logical operands.

What's wrong with if (json.RowKey != json.NewRowKey)

I am using lint and for the following:
if (json.RowKey != json.NewRowKey)
It gives me a message:
Expected '!==' and instead saw '!='.
Can someone explain what this means?
== will attempt to convert the types of the two operands to be the same before comparing them. Thus "2" == 2 is true.
=== will not attempt to convert the types of the two operands so if they are not the same type, they will never be ===. Thus "2" === 2 is false.
It is better to use === and !== as your default choice and only use == or != when you explicitly want to allow type conversion. If you are not expecting the two operands to be different types, then === and !== is more likely to do what you are expecting.
This avoids coding mistakes when things are not really equal and your code doesn't intend for them to be equal.
Some odd things that happen with == (and do not happen with ===) that you may not expect and can lead to trouble. All of these evaluate to true:
null == undefined
false == '0'
0 == '0'
0 == ''
There's more detail written here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
!== is not equal (neither value or type)
Eg:
var x = 5; x !== "5" returns true
var x = 5; x !== 5 returns false
It's a warning that tells you that you should consider using the !== operator instead of !=.
On the surface they both do the same thing - compare whether the two items are not equal. However, !== makes sure that both items are of the same type first (that is, it won't try to convert, say, a string to a number if one item being compared is a string and the other is a number), so it's generally safer to use and helps you avoid comparison errors.
For more details, see here: Which equals operator (== vs ===) should be used in JavaScript comparisons?
Yes,
if("1" == 1) //Returns true because it will convert the second 1 into a string to match
but
"1" !== 1 //Returns false because the first 1 is a string and the second 1 is an integer.
We are talking about variable types; with two equal signs, javascript (and php) will typecast the variable for you (convert the integer 1 into a string 1 to make the match and be true), but with the second statement, it will not.
1 === 1 //True
1 === "1" //False
1 == "1" //True
1 == 1 //True
Hope my answer makes sense to you.

Javascript equality triple equals but what about greater than and less than?

I was explaining to a colleague that you should use === and !== (and >== and <== of course) when comparing variables in JavaScript so that it doesn't coerce the arguments and get all froopy and confusing but they asked me a two part question that I did not know the answer to and thought I would ask the experts here, specifically it is:
What about > and < - when they compare do they also coerce the arguments or not - why isn't there some sort of >> and << operator (probably need to be some other syntax as I would guess they would be bit shift operators if it is going along the whole C style but you get the gist)?
So I can write a test to find the answer to the first part, which I did, here it is:
// Demo the difference between == and ===
alert(5 == "5");
alert(5 === "5");
// Check out what happens with >
alert(5 > "4");
alert(5 > 4);
and it returned:
true
false
true
true
so it does look like the > is doing the coercion since > "4" and > 4 return the same result. so how about the second part...
Is there some sort of operator for > and < that do not coerce the type (or how can I change my test to perform the test safely)?
No, there's no need for such operators. The type checking done for those relational operators is different than for equality and inequality. (edit — perhaps it's a little strong to say that there's "no need"; that's true only because JavaScript deems it so :-)
Specifically, the > and < and >= and <= operators all operate either on two numeric values, or two strings, preferring numeric values. That is, if one value is a number, then the other is treated as a number. If a non-number can't be cleanly converted to a number (that is, if it ends up as NaN), then the result of the comparison is undefined. (That's a little problematic, because undefined will look like false in the context of an if statement.)
If both values are strings, then a collating-order string comparison is performed instead.
If you think about it, these comparisons don't make any sense for object instances; what does it mean for an object to be "greater than" another? I suppose, perhaps, that this means that if you're finding yourself with values of variant types being compared like this, and that's causing problems, then yes you have to detect the situation yourself. It seems to me that it would be good to work upstream and think about whether there's something fishy about the code that's leading to such a situation.
Is there some sort of operator for > and < that do not coerce the type
No.
how can I change my test to perform the test safely
You would have to explicitly test the types:
typeof a === typeof b && a > b
I referenced Flanagan's JavaScript: The Definitive Guide (5th Ed.) and there does not seem to be non-coercive comparison operators.
You are right in saying the << and >> are indeed bitwise operators so that wouldn't work.
I would suggest you deliberately coerce the values youself:
var num_as_string = '4';
var num = +num_as_string;
if (5 > num) { ... }
12 > '100' // false
'12' > 100 // false
'12' > '100' // true
As others mentioned, if one is a number the other is casted to a number. Same rule applies to these cases as well:
null > 0 // false
null < 0 // false
null >= 0 // true
However, there might be cases that you would need null >= 0 to give false (or any of the number string comparison cases above), therefore it is indeed a need to have strict comparison >== or <==.
For example, I am writing a compareFunction for the Array.prototype.sort() and an expression like x>=0 would treat null values like 0's and put them together, whereas I want to put them elsewhere. I have to write extra logic for those cases.
Javascript says deal with it on your own (in practice).

Javascript if-statement vs. comparsion

Is it true that in if-statement JavaScript wrap the condition into a Boolean?
if(x) => if(Boolean(x))
Is it true that in comparison JavaScript wrap the compare elements into a Number?
a == b => Number(a) == Number(b)
Yes, and No.
For the first part, yes, that is essentially what the javascript does.
But for the latter, no. Not everything in JavaScript can be converted to a number. For example:
Number('abc') // => NaN
And Not-A-Numbers are not equal:
NaN == NaN // => false
So something like this:
Number('abc') == Number('abc') // => false!
But that's actually true with equality comparison.
'abc' == 'abc' // => true
As a side note, it's probably better to use === in JavaScript, which also checks the type of the values being compared:
0 == '0' // => true
0 === '0' // => false, because integer is not a string
More details about === can be read over here.
Yes, that's true, x is evaluated in a boolean context in this situation, so the equivalent of Boolean(x) is applied.
No, that's not true. It only looks that way because the coercitive equality operator == tries to convert a and b to the same type. Number() is only applied if either a or b is already a Number. For instance:
>>> 0x2A == 42
true // both 'a' and 'b' are numbers.
>>> "0x2A" == 42
true // 'a' is a string whose number coercion is equal to 'b'.
>>> "0x2A" == "42"
false // 'a' and 'b' are different strings.
Is it true that in if-statement JavaScript wrap the condition into a Boolean?
Usually yes.
Is it true that in comparison JavaScript wrap the compare elements into a Number?
Absolutely no.
Explanation
From JavaScript Language Specifications.
The if statement is defined at § 12.5 as:
if ( Expression ) Statement else Statement
It says that the Expression will be evaluated, converted with GetValue() and then tested after the ToBoolean() conversion.
Then the first assertion is true (but see later), the condition for the if statement is evaluated like is passed as parameter to the Boolean function. Please recall how JavaScript handles type conversion to boolean (§ 9.2):
undefined and null values are converted to false.
numbers are converted to false if ±0 or NaN otherwise they're converted to true.
strings are converted to false if empty otherwise always to true regardless their content.
objects are always converted to true.
Because of the call to GetValue() strictly speaking this assertion is not always true, take a look to § 8.7.1 where the standard describes how GetValue() works, here can happen some magic conversion before ToBoolean() is called.
The == operator is defined as in § 11.9.3.
As you can see it doesn't specify that operands must be (or will be treated as) numbers, the behavior of the operator is different and regulated by a series of rules based on the type of the operands. Then your second assertion is false. The case they're numbers (or one of them is a number) is just a special case in the algorithm, please note that at point 4 of the algorithm it says that if one of them is a number and the other one is a string then it'll be converted with ToNumber(), only in this case (with all the implications that this conversion has).
It's intuitive if you think that you can compare functions, strings or numbers, not every type can be converted to a numeric value.

Categories

Resources