Search code examples
javascripttype-coercion

why resolve this "b" == ([] +{})[!+[]<<!+[]]) to true


Can anyone explain this?

console.log("b" == ([] +{})[!+[]<<!+[]])

I can imagine it has something to do with type conversion. but the <<! get me really confused


Solution

  • Break down the expression ([] +{})[!+[]<<!+[]] to see how it resolves to b:

    ([] +{}) [!+[]<<!+[]]
    

    The expression inside the left parentheses resolves to [object Object], because both the [] and {} are coerced to strings (but the empty array, coerced to a string, is the empty string). So now you have

    '[object Object]' [!+[]<<!+[]]
    

    Break down the expression inside of the square brackets:

    !+[]<<!+[]
    

    Group using operator precedence, and you get:

    (!+[]) << (!+[])
    

    And !+[] is true: +[] tries to convert the empty array to a number, but turning the empty array to a primitive results in the empty string, which is falsey, so the number is 0. ! inverts the truthyness of that, resulting in true. So

    (!+[]) << (!+[])
    

    is equivalent to

    true << true
    

    Which is bitwise left-shift on their numeric equivalents:

    1 << 1
    

    which is 2. So

    '[object Object]' [!+[]<<!+[]]
    

    turns into

    '[object Object]' [2]
    

    or 'b`.