Search code examples
javascriptcomparisontruthiness

If ([] == false) is true, why does ([] || true) result in []?


Was just doing some testing and I find this odd:

[] == false

Gives true, this makes sense because double equal only compares contents and not type and tries to do type-coercion. But if its comparing contents and returns true, that means [ ] is falsey (if you did [] == true you get false too), which means:

[] || false

Should give false, but it gives [ ], making it truthy? Why?

Another example:

"\n  " == 0

Gives true, but "\n " || false gives "\n "? Is there an explanation for this or its just an oddity.

When I tried this in C, we get:

int x = "\n " == 0;
printf("%d\n", x);

int y = "\n " || 0;
printf("%d\n", y);

Outputs:

0
1

This makes sense, but given C's influence on Javascript, the behaviour is different.


Solution

  • Type conversion is not related to falsy and truthy values.

    What is truthy and what is falsy is defined by the ToBoolean function defined in the specs and [] is indeed truthy.

    On the other hand, [] == false returns true because of the type conversion that happens during the evaluation of the expression.

    The rules of type conversion say that for x == y

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

    ToNumber results in 0 for false so we're left with the evaluation of [] == 0. According to the same rules

    If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

    ToPrimitive results in an empty string. Now we have "" == 0. Back to our type conversion rules

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

    ToNumber results in 0 for "" so the final evaluation is 0 == 0 and that is true!