Reputation: 2351
Can anyone explain this?
console.log("b" == ([] +{})[!+[]<<!+[]])
I can imagine it has something to do with type conversion. but the <<!
get me really confused
Upvotes: 1
Views: 65
Reputation: 37755
Let's understand it step by
When you do arithmetic opreation on array it internally calls toString
console.log([]+ 1, typeof ([] + 1))
so the ([]+{})
will result in "[object Object]"
console.log([] +{})
When you use +
unary operator which tries to change the operand to numeric values
console.log(+[])
so now
(!+[] << !+[]) which is equal to ` 1 << 1`, so left shifts result in `2`
SO your simplified expression is
console.log("b" == "[object Object]"[2] )
This operator shifts the first operand the specified number of bits to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.
Left shift MDN
so 1 is represent as 01
in binary, so 1 << 1
will shift the binary by 1 position so it will become
`10` -> in binary representation,
Which is equal to 2
in decimal format
console.log(1<<1)
console.log((2).toString(2))
console.log(parseInt("10",2))
Upvotes: 3
Reputation: 371019
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`.
Upvotes: 4