Why does 1==1==1 return true, "1"=="1"=="1" return true, and "a"=="a"=="a" return false?
JavascriptJavascript Problem Overview
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?
Javascript Solutions
Solution 1 - Javascript
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
.
Solution 2 - Javascript
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. :-/
Solution 3 - Javascript
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.
Solution 4 - Javascript
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 (==).
Solution 5 - Javascript
It's true that (1 == 1) == 1
. Then it will be true == 1
, but not in a == a == a
.
Solution 6 - Javascript
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