Why does (![]+[])[+!![]+[]]
produce "a"
step by step: this is parsed in: (![]+[])
and [+!![]+[]]
. First bit was already explained by artemb: []
is an array. Negating it, ![]
evaluates to a boolean, false
- that's just how !
works when it is applied to something that is not null
or undefined. Again as pointed out by artemb, appending this +[]
forces the boolean to be converted to a string. That's because the +
is a string concatenation operator. The boolean false
is then converted to its string representation, "false"
.
Then, the second bit, [+!![]+[]]
. First of all, the outer [
and ]
serve to treat the preceding string, which we just dervived is equal to "false"
as an array of characters. By putting an integer index inside the [
and ]
, you get the character at a particular index. So what remains is +!![]+[]
This consists of 4 pieces: +
, !![]
, +
and []
. First !![]
is evaluated. We already saw that ![]
is a boolean false
so prepending another !
negates it, and yields true
. Next thing what happens is that the +
in +!![]
gets applied, and by applying +
it converts the boolean true
into the number representation, which is 1
(so +true
is 1
) The +[]
that follows makes a string again from that 1
yielding "1"
but it does not really make sense, the shorter expression (![]+[])[+!![]]
already produces a
. Appending +[]
doesn't hurt either, the resulting expression is simply ["1"]
instead of [1]
. My hunch is that when []
is applied to an array, whatever is inside the []
will be coerced into a number, which for "1"
would give 1
again. So either way, +!![]+[]
evaluates to 1
, making the final expression: "false"[1]
which is saying: gimme the character at index 1 from the string "false"
, and since by default, arrays start at 0
in javascript, this is the second character of "false"
, and a
.