111

Why is the result of the following two statements different?

('0' ? 'a' : 'b') /* -> 'a' */
('0' == true ? 'a' : 'b') /* -> 'b' */

jsFiddle testcase

Edit:

I should add that I suspect the '0' first statement to be cast to boolean to be compared - which should be exactly the same as " '0' == true " Obviously this is not true.

Strayer
  • 3,050
  • 3
  • 30
  • 40

6 Answers6

207

First, for completeness:

('0' ? 'a' : 'b') 

is 'a', because '0' is a non-empty string, which always evaluates to true:

String: The result is false if the argument is the empty String (its length is zero); otherwise the result is true.


Now to '0' == true.

Two type conversions will take place here. We can follow this in the specification, section 11.9.3, The Abstract Equality Comparison Algorithm.

The operands are denoted as x and y (x == y).

In our case, x is a string ('0') and y is a Boolean (true). Hence step 7 is executed:

If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

When booleans are converted to numbers, the following conversion takes place:

Boolean: The result is 1 if the argument is true. The result is +0 if the argument is false.

Now we have

'0' == 1

which matches the condition in step 5:

If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

How strings are converted to numbers is more complex but of course can also be found in the specification.

So the final comparison is

0 == 1

which is false (step 1. a. vi.)

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
8
('0' ? 'a' : 'b'); /* -> 'a' */

0 is a string value, every non-empty string is evaluated as true, and not tested as boolean. If quotes are removed:

(0 ? 'a' : 'b'); /* -> 'b' */

you will receive b - now 0 is not a string and evaluated as false!

('0' == true ? 'a' : 'b'); /* -> 'b' */

0 is evaluated as bool Both are evaluated as numbers, which is false. Point 11.9.3 The Abstract Equality Comparison Algorithm from the specs show that a number of conversions may be executed to compare the same type of variables.

Bakudan
  • 19,134
  • 9
  • 53
  • 73
  • Actually, your statement that '0' is evaluated as a boolean is not correct, what actually happens is that _true_ is evaluated as a number, which then forces '0' to be evaluated as a number. This comes as a direct result of the spec that you point to. See also the answer of Felix King. – Paul Wagland Sep 27 '11 at 04:55
3

Because '0' is not equal 1, so it is not equal to true, though it is not false. In the first case, when '0' is casted to bool, casting operator returns true for everything that is not 0.

Alex F
  • 42,307
  • 41
  • 144
  • 212
1

Mostly because JavaScript is pretty darn inconsistent when it comes to truth-iness. But the answer is:

  1. In this case, '0' is converted directly to a Boolean, and '0', being a non-empty string, is true.
  2. In this case, no conversion takes place; a string is not equal to a boolean value.
Michael Aaron Safyan
  • 93,612
  • 16
  • 138
  • 200
  • 4
    Well, ('1' == true) is true ;) There is no === in the second statement. – Strayer Sep 21 '11 at 08:52
  • 1
    I think it is pretty consistent, the problem is how we are trying to use it. There are some things that were not meant to be used as we think. But all this is a matter of interpretation, which leads to different solutions and etc, not some universal truth like in math. :) – Bakudan Sep 21 '11 at 09:04
  • 8
    Your second point is wrong. conversion *does* take place. – Felix Kling Sep 21 '11 at 09:29
-3

That's because '0' is trueish (in an if statement), but not considered equal to true. Just like both 3 and 17 are trueish, but not equal.

Erich Kitzmueller
  • 36,381
  • 5
  • 80
  • 102
-4

('0' ? 'a' : 'b') --> 0 is false, '0' is some string therefore NOT FALSE 0,null or '' (empty string) is treated as FALSE in this case

('0' == true ? 'a' : 'b') --> as mentioned by others some_string compared to boolean TRUE is NOT TRUE

Jan Pfeifer
  • 2,854
  • 25
  • 35