Search code examples
javascriptequalitycoercion

How does JS type coercion work?


I'm learning about == vs. === and came across this answer which was very helpful in understanding the concept. However I wondered about one of the examples:

'0' == false     // true

This might make sense, since == doesn't check for type. But then I tried some possible coercions in the console and found the following:

Boolean('0')     // true
String(false)    // "false"

I would have thought '0' == false has the same truth value as '0' === String(false), but that doesn't seem to be the case.

So how does the coercion actually work? Is there a more basic type I'm missing?


Solution

  • "0" is a string containing the character 0, it is not the numeric value 0. The only string-type value which evaluates to false is "".

    "0" is truthy.

    Section 9.2 of the ECMAScript 262 specification defines how different types are converted to Boolean:

    Argument Type   Result
    Undefined       false
    Null            false
    Boolean         The result equals the input argument (no conversion).
    Number          The result is false if the argument is +0, −0, or NaN; otherwise the
                    result is true.
    String          The result is false if the argument is the empty String (its length is
                    zero); otherwise the result is true.
    Object          true
    

    This, however, is only strictly followed when comparing using ===.

    When using Boolean('0') you're converting the value '0' to Boolean (which is the same as using !!'0'). When loosely comparing '0' with false, the Boolean value is converted to a number (as defined here). false, when converted to a number, becomes 0. This means the final calculation is '0' == 0 which equates to true.

    To summarise the relevant part of the linked section of the ECMAScript specification above:

    1. Let x = '0' and y = false.
    2. Check if the type of y is Boolean.
    3. If true, convert y to a number.
    4. Compare x to the numeric equivalent of y.

    In our case, a JavaScript implementation of this would be:

    var x = '0',                      // x = "0"
        y = false;                    // y = false
    
    if (typeof y === "boolean") {
        y = +y;                       // y = 0
    }
    
    console.log( x == y );            // "0" == 0
    
    -> true