114
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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chris97ong
  • 6,870
  • 7
  • 32
  • 52
  • 79
    Hint: X == Y == Z is evaluated as ((X == Y) == Z). – Blackhole May 09 '14 at 09:51
  • 14
    Strangely, `true == "1"` evaluates to `true`. – Codor May 09 '14 at 09:53
  • 14
    Related: [Why does (0 < 5 < 3) return true?](http://stackoverflow.com/q/4089284/218196) – Felix Kling May 09 '14 at 09:57
  • 4
    possible duplicate of [Does it matter which equals operator (== vs ===) I use in JavaScript comparisons?](http://stackoverflow.com/questions/359494/does-it-matter-which-equals-operator-vs-i-use-in-javascript-comparisons) and [Difference between == and === in JavaScript](http://stackoverflow.com/questions/523643/difference-between-and-in-javascript). –  May 09 '14 at 12:17
  • 1
    @Cupcake question is different from you referring. – Zaheer Ahmed May 09 '14 at 12:31
  • 11
    @Cupcake: In good faith, I think the main headscratcher here is that an equality that appears to be true mathematically is actually false as far as JS is concerned, not that e.g. `true == 1` is true. In other words, the aha moment is not realizing that the types play a part but rather that all of these are comparing something to `true`. I 'm sure there's a dupe of this somewhere, but IMO it's not one of those you offer. – Jon May 09 '14 at 12:45
  • 1
    @Jon ok, that's a fair argument. You've spent more time in this tag than I have, so I'll defer to you. –  May 09 '14 at 12:58
  • 2
    @Blackhole You just _sucked_ the first thought I had upon seeing this in the "hot" questions. – Cole Tobin May 09 '14 at 16:28
  • 2
    Javascript's definition of true and false is wicked blackmagic. – Hello World May 10 '14 at 13:10
  • 2
    Here are a few more dupes: http://stackoverflow.com/questions/22980471/how-does-a-b-c-comparison-work-in-javascript http://stackoverflow.com/questions/19955573/why-is-1-1-1-false, this time with the == and === operator – Niklas B. May 10 '14 at 14:53

6 Answers6

185

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.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • 27
    It's also worth mentioning that using strict equal (`===`) operator will prevent this unexpected behaviour for `"1"` – Konrad Gadzina May 09 '14 at 10:16
  • 12
    @KonradGadzina: Strict equals will make all three functions return `false`. – Jon May 09 '14 at 10:18
  • 1
    You're right. I've seen so many `true` in here that I forgot about that. ^^ – Konrad Gadzina May 09 '14 at 10:20
  • @Jon: `So what happens in c is that "a" is converted to a number (giving NaN)` neither operand is a number. I think the conversion ends up with `"true" == "a"` rather than `1 == NaN`. – Flater May 09 '14 at 12:57
  • @Flater I disagree. See https://en.wikipedia.org/wiki/Boolean_data_type#Python.2C_Ruby.2C_and_JavaScript – Jonathan E. Landrum May 09 '14 at 13:00
  • 5
    @Flater: No. The passage I have quoted above is very clear on what exactly happens ("if either operand is a number *or a boolean*" -- the left hand side operand *is* boolean). It's also very easy to see that your assertion is wrong: `1 == 1 == "true"` => `false`. – Jon May 09 '14 at 13:02
  • I stand corrected. Thanks for the reply ;à – Flater May 12 '14 at 06:57
26

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. :-/

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Von Lion
  • 748
  • 4
  • 22
  • 5
    JavaScript for sure does **not** have *its roots in the C-family of languages*. It has its roots in LISP dialects such as Scheme, and was inspired by Self as well. It only uses the syntax of C, but not its semantics. IMHO this is one of the most widespread and quite wrong misunderstandings of JavaScript. To underline this, please also have a look at Douglas Crockford's article [JavaScript: The World's Most Misunderstood Programming Language](http://javascript.crockford.com/javascript.html). – Golo Roden May 09 '14 at 19:04
  • 3
    @GoloRoden: Don't be silly. If JavaScript didn't have C's semantics, a number of classic C semantical bugs such as `if (x = 5)` would not exist in JS... but they do, exactly as in C. IT certainly doesn't have *all of* C's semantics, but it behaves a lot more like C than like any Lisp. – Mason Wheeler May 09 '14 at 22:25
  • 5
    @MasonWheeler assignments in conditions is NOT a bug or defect. – Miles Rout May 10 '14 at 03:32
  • 3
    @MilesRoul: Try telling that to... well... *everyone who's ever been bitten by it.* – Mason Wheeler May 10 '14 at 05:06
  • @Masonwheeler is this really that common amongst anyone other than complete newbies? I've never ever done that by accident in 15 years. – funkybro May 10 '14 at 07:04
  • 2
    @funkybro Being a pro doesn't mean accidents can't happen. I have been programming C for over 10 years and lately I found myself forgetting the `break;` in a C `switch` statement... – glglgl May 10 '14 at 09:41
  • 1
    MasonWheeler: you're confusing "having roots" with "including poor design to appease the masses". The history of JavaScript is well documented. – nomen May 10 '14 at 16:47
  • @nomen So true, but hey, "Don't be silly" ... ;-)) – Golo Roden May 10 '14 at 17:55
6

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.

La-comadreja
  • 5,627
  • 11
  • 36
  • 64
5

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

nomen
  • 3,626
  • 2
  • 23
  • 40
2

It's true that (1 == 1) == 1. Then it will be true == 1, but not in a == a == a.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sdfc
  • 29
  • 1
1

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

wuiyang
  • 409
  • 2
  • 5
  • 18