Hacker Newsnew | comments | show | ask | jobs | submit login

I'm missing the basics for this one. Why does ++[[]][+[]] == 1?



To start, you need to know that JavaScript has type coercion. Numbers can become strings, strings can become numbers, and arrays can become strings.

Thus, for example: [] in a string context becomes "". "" in a number context becomes 0. Thus if we were to do: "" - 1 we'd get the number -1. Additionally if we were to do [] - 1 we'd get -1. ++ is also able to coerce a string into a number.

If ++ is able to turn a string into a number then you're probably wondering why they just don't do ++[] and be done with it (to get 1, that is). The problem is that ++ is attempting to assign that resulting value back somewhere and since [] doesn't exist anywhere yet (it's temporary) it throws an error instead.

We could do something like this:

    var a = [];
    ++a; // 1
But we can't actually assign the result to a variable because we can't use alphanumeric characters. So what's another way in which we can assign the results to a variable? We can stick it into an array.

    var a = [ [] ];
    ++a[ 0 ]; // 1
This also works:

    ++[ [] ][ 0 ];
Now, we can't use 0 because it's alphanumeric so we swap 0 for +[] (+ turns the string "" into the number 0, [] turns into the string ""). Thus we get the final result:

    ++[ [] ][ +[] ]

-----


The explanation of why ++[] throws error is actually incorrect. This has nothing to do with "existence" of [] (I'm not even sure what existence could mean here). Rather, it's the way ++ operator works.

++ requires its operand to evaluate to a _reference_, not a _value_. If operand evaluates to a value, a ReferenceError is thrown (well, actually it is internal PutValue method that throws error, but that's irrelevant here). Now, if we were to pass reference to ++ operator, it would "work" as expected. E.g.:

++({ x: 1 }).x;

In this case, `({ x: 1 }).x` is a reference, it evaluates to 1, and is then increased by 1 to produce 2 as a resulting value.

When you said "this also works" with `++[ [] ][ 0 ]` example, what happened is that `[ [] ][ 0 ]` evaluated to a reference too, and returned a value of array (inner one). The fact that something like ++[[]][0] "works" should already hint at the fact that "existence" of an object is a bogus reasoning ;)

So what we really need to understand here (besides type coercion) is the notion of references. Literals, for example, always evaluate to values: 1, "foo", true, ({ x: 1 }), and [] are all values. Expressions involving property accessors, on the other hand — foo.bar, [1][0], ({ x: 1 }).x — are all references.

Understanding this distinction can also help explain other aspects of Javascript, such as, say, simple assignments, where left hand operand is constrained by the same rules as ++ operator; it should always evaluate to a reference:

1 = 1; // ReferenceError, LHS operand is not a reference

null = 1; // ReferenceError, LHS operand is not a reference

// but

({ x: 1 }).x = 1; // works as expected, LHS operand is a reference

x = 1; // works as expected, LHS operand is a reference

FWIW, it is the same internal PutValue method that's invoked by `=` operator, and is why assignment to non-reference values result in an error.

-----


"This has nothing to do with 'existence' of [] (I'm not even sure what existence could mean here)."

Ah sorry, I was referring to the fact that the array was already created and within another object that we were referencing. But yeah, thanks for your more-in-depth explanation!

-----


Qualification test to be able to join the jQuery team

-----


You can even do that in half the bytes by making use of all unary operators together:

  -~+[]
-~ is a good proxy for ++ when incrementing unassigned variables.

-----


That's some JavaScript kung-fu skill.

Excellent comment, thanks.

-----


I did not get this line.

But we can't actually assign the result to a variable because we can't use alphanumeric characters.

-----


You can't just write "var a = ..." because the goal is to use only "[]{}()+/."

-----


damn, that is clever - I think it may have usurped the django pony in terms of magic ;)

-----


The first block (++[[]]) is incrementing in a object but the object is superimposed with other object and the result is error.

the second block [+[]] when [] is object but incrementing + is a number 0 and side-by-side with the block the result is exactly 1.

-----




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: