Does operator precedence matter for && and == in javascrtipt? - javascript

More specifically, is there a set of values ( a, b and c) for which the operator precedence matters in the statement:
var value = (a && b == c);
(with the exception of NaN).

Yes
js> false && true == false
false
js> (false && true) == false
true
Since == has higher precedence than &&, the first is parsed as false && (true == false), which is equivalent to false && false, and thus evaluates to false. The second is equivalent to false == false, which is true

The language is parsed such that your statement is the equivalent of (a && (b == c)). The equality operator will always run before &&, || and other logical operators. You can find the nitty-gritty details here.

Yup. == binds more tightly than &&, so what you have binds as
var val = a && ( b == c)
See here. So a==0, b==1 and c==0 is false, while (a&&b)==c is true.
(Fixed typo. Dammit.)

Related

Why 0 && true echo 0 in js?

As title
As I know
(if this part is true) && (this part will execute)
if(condition){
(this part will execute)
}
0 is false, so why not echo false but 0?
Because operator && return first falsey element otherwise they return last element
1 && 0 && false // 0
1 && 2 && 3 // 3
From MDN:
expr1 && expr2 -- Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
expr1 || expr2 -- Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true.
!expr -- Returns false if its single operand can be converted to true; otherwise, returns true.
Some expressions that can be converted to false are:
null
NaN
0
empty string("" or '' or ``)
undefined
Short-circuit evaluation
As logical expressions are evaluated left to right, they are tested for possible "short-circuit" evaluation using the following rules:
false && (anything) is short-circuit evaluated to false.
true || (anything) is short-circuit evaluated to true.
The JavaScript documentation of logical operators explains:
Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value. However, the && and || operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they may return a non-Boolean value.
In javascript all except for null, undefined, false, 0, and NaN are Truthy.
In your case, why not echo false but 0?.
Javascript's ToBoolean function evaluates it to the first falsey value. i.e,
0 && true
=> 0
true && undefined
=> undefined
null && undefined
=> null
And if you need either strictly true or false, then go for not-not i.e, !!.
!!0 && true
=> false
!!true && undefined
=> false
!!null && undefined
=> false
(something falsy) && (anything) will always return false.
Also 0 is falsy and '0' (a non empty string) is truthy
a && b is equivalent to
if (a) {
return b;
} else {
return a;
}
So in your case a equals to 0, which is falsy, therefore you get a.
Unlike other languages, JavaScript does not return true or false on && and ||, it returns the first truthy operand for a || operator, or the last one, and the first falsy operand for the && operator, or the last one.
You can find more info here.
For && operator comparing with false is always FALSE.
0 && false => 0
false && 0 => false
for better understanding :-
In case of && operator (always start from left-right), when you get the value 0 (false) it will print 0(false); if start with false it will directly print false. it won't check the second operand when get false.
but in case
true && 1 => 1
1 && true => true
as it has to check till end and ultimately give the end operand as result if won't get false.
For || operator comparing with true is always TRUE.
1 || true => 1
true || 1 => true
for better understanding :-
In case of || operator (always start from left-right), when you get the value 1 (true) it will print 1(true).
Starting with true it will directly print true. it won't check the second operand when get true.
but in case
false || 1 => 1
0 || true => true

Does strict equality guarantees loose equality

I'm starting to write unit tests for my nodeJS/Javascript app with Mocha.
For my equality assertions tests I decided to use
assert.strictEqual to test for equality
assert.notEqual to test for difference
The idea behind this is to enforce the use of the strict equality operator (=== and !==) but to be sure no error will be produced if == and != are used.
But it led me to a question :
For every possible a does a === b means a == b and does a !== b means a != b ?
The === and !== ensure that no only are the items considered 'equal' but that they are the same type - no type coercion is done:
"1" == 1 //true
"1" === 1 //false
It's the same for the inequality operator:
"2" != 1 //true
"2" !== 1 //true
"1" != 1 //false
"1" !== 1 //true
So, short answer, "For every possible a does a == b means a === b and does a != b means a !== b ?" - No.
No. For example 0 !== false yet 0 == false.
The === comparison is stronger than ==. A == comparison just checks if two values are equal, performing type conversions as needed. A === comparison check that both the type and the value are the same. So a === b implies a == b, and a != b implies a !== b.
Example:
"100" == 100 -> true
"100" === 100 -> false
"100" != 100 -> false
"100" !== 100 -> true

Why does 1==1==1 return true, "1"=="1"=="1" return true, and "a"=="a"=="a" return false? [duplicate]

This question already has answers here:
How does (A == B == C) comparison work in JavaScript?
(6 answers)
Closed 8 years ago.
function a() { return (1 == 1 == 1); }
function b() { return ("1" == "1" == "1"); }
function c() { return ("a" == "a" == "a"); }
I tested the above code in Chrome's console and for some reason, a() returns true, b() returns true, and c() returns false.
Why is this so?
Because you are comparing the (boolean) result of the first equality with the (non-boolean) third value.
In code, 1 == 1 == 1 is equivalent to (1 == 1) == 1 is equivalent to true == 1.
This means the three methods can be written more simply as:
function a() { return (true == 1); }
function b() { return (true == "1"); }
function c() { return (true == "a"); }
These comparisons work according to these rules (emphasis mine):
If the two operands are not of the same type, JavaScript converts the
operands, then applies strict comparison. If either operand is a
number or a boolean, the operands are converted to numbers if
possible; else if either operand is a string, the string operand is
converted to a number if possible. If both operands are objects, then
JavaScript compares internal references which are equal when operands
refer to the same object in memory.
So what happens in c is that "a" is converted to a number (giving NaN) and the result is strictly compared to true converted to a number (giving 1).
Since 1 === NaN is false, the third function returns false. It's very easy to see why the first two functions will return true.
Because 1 == true
But "a" != true
So basically what happens is that
1 == 1, "1" == "1" and "a" == "a" are all evaluated to be true and then compared to the next value.
The string "1" is converted to a number (1) prior to being compared to true and is thus also considered to be equal to true.
Now, the "WHY?!?!" question is explained by the fact that Javascript has its roots in the C-family of languages. In which any number, other than 0 is considered to be a valid true boolean. :-/
Because 1 and "1" are both converted to true, as numbers. This is not the case with "a". Therefore:
("1" == "1" == "1")
evaluates to
(("1" == "1") == "1")
which evaluates to
(true == "1")
Similarly,
("1" == 1 == "1")
is also true, or any combination thereof. In fact, any non-zero number when converted to a boolean is true.
Whereas, "a" does not evaluate to true.
It's because JavaScript is a weakly typed language. This means that it is not expressive enough to talk about types, and in fact implicitly coerces values to belong in types to which they have no semantic relation. So, (1 == 1) == 1 evaluates to true because (1 == 1) correctly evaluates to true, so that JavaScript evaluates (true) = 1. In particular, it is turning 1 to a boolean (or true to a number -- I forget which, but the result is effectively the same).
The point is that JavaScript is turning one type of value into another type of value behind your back.
Your question shows why this is a problem: ('a' == 'a') == 'a' is false, because ('a' == 'a') is true, and JavaScript ends up comparing (true) == 'a'. Since there is just no sensible way to turn a Boolean into a letter (or a letter into a boolean), that statement is false. Of course, that breaks referential transparency for (==).
It's true that (1 == 1) == 1. Then it will be true == 1, but not in a == a == a.
Boolean handled as bits, each bit stands for true or false ( 1 for true, 0 for false )
so that 1 stands for true, and 0 stand for false
and 1 == 1 == 1 will be like (1 == 1) == 1, true == 1, true
while 'a' == 'a' == 'a' will be ('a' == 'a') == 'a', true == 'a', false
BONUS: 0 == 1 == 0, 1 == 0 == 0 and 0 == 0 == 1 returns true

How to have multiple 'and' logical operators and an 'or' logical operator

It is slightly hard to explain but I want to do something that looks like this:
if(a === 4 && b === true && c === "words" || "numbersandwords")DoSomething();
but it ends running without it matching the first operators. I want to know how to have the last operator except 2 different inputs while still making sure the other criteria are met before running.
You just need to use parentheses, e.g.:
if(a == 4 && b == true && (c == "words" || c == "numbersandwords")) { DoSomething(); }
Just use a few brackets to separate your or parts and the and parts, and add the c === before the last string. Without that equality part at the end, the 'numbersandwords' string always equates to true.
if(a === 4 && b === true && (c === "words" || c === "numbersandwords")){
DoSomething();
}
In JavaScript, like other languages, every operator (like && and ||) has a precendence that determines the order in which it's evaluated. && has higher precedence than ||, so it's evaluated first. Therefore, every term on the left is anded together. Even if they are all false, however, the overall result is true because it's ored with "numbersandwords", which evaluates to true (as does everything except 0, -0, null, false, NaN, undefined, or the empty string). The first thing you need to do is actually compare something (presumably c) to it. Then you can change the order of evaluation using parentheses, which has higher precedence than anything else:
if(a === 4 && b === true && (c === "words" || c === "numbersandwords")) DoSomething();
Alternatively, you can break the test up into several if statements if you may want to eventually do something slightly different based on the value of c (or it just better expresses your intent):
if(a === 4 && b === true)
{
if(c === "words" || c === "numbersandwords")
{
DoSomething();
}
}

When is (true == x) === !!x false?

JavaScript has different equality comparison operators
Equal ==
Strict equal ===
It also has a logical NOT ! and I've tended to think of using a double logical NOT, !!x, as basically the same as true == x.
However I know this is not always the case, e.g. x = [] because [] is truthy for ! but falsy for ==.
So, for which xs would (true == x) === !!x give false? Alternatively, what is falsy by == but not !! (or vice versa)?
"So, for which xs would (true == x) === !!x give false?"
Any x where its Boolean conversion is not the same as its conversion by the Abstract Equality Comparison Algorithm.
An example is a string with only whitespace:
var x = " ";
Its Boolean conversion is true (as is the case with any non-empty string), but its == comparison is false because a string with only white space will be converted to the number 0, and the true value will be converted to the number 1, and those values are not equal.
x == true; // false
!!x; // true
or to show the ultimate values the == is comparing:
Number(true) == Number(x);
// 1 == 0
1 == 0; // false
and to show the result of !!x, it would be equivalent to this:
Boolean(x); // true
So your original expression could crudely be seen as the following:
var x = " ";
(Number(true) == Number(x)) === Boolean(x);
// ( 1 == 0 ) === true
// ( false ) === true
false === true; // false
I say "crudely" because this certainly doesn't capture all the detail of the algorithm linked above, and won't be the same for all values provided to the operands.
To understand how == treats its operands, you really need to study the algorithm a bit.
Loose equality has nothing to do with truthiness.
The rules for loose equality basically involve comparing the results of the .valueOf() function for each object.
For more details, see the spec.

Categories