Why does ('0' ? 'a' : 'b') behave different than ('0' == true ? 'a' : 'b') [duplicate]

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.


Solution 1:

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

Solution 2:

('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.

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

Solution 4:

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.