Why ++[[]][+[]]+[+[]] evaluates to “10″ in JavaScript

This comes from a popular question on Stack Overflow. Given the popularity of the question, the fact that it is now closed and the fact that the highest-ranked answer there is a little imprecise, I’ve decided to write up an explanation here.

I should warn you now that I’m going to make reference to the ECMAScript specification to explain this. It shouldn’t get too painful though. I’m using version 3 rather than the more recent version 5 of the spec for two reasons: first, it’s still the baseline for what is supported in mainstream browsers, and second, there’s a handy HTML version on the web that lets me link to the relevant sections. So, with that out of the way, onto the code.

The expression ++[[]][+[]]+[+[]] may initially look rather imposing and obscure, but is actually relatively easy break down into separate expressions. Below I’ve simply added parentheses for clarity; I can assure you they change nothing, but if you want to verify that then feel free to read up about the grouping operator. So, the expression can be more clearly written as

(++[[]][+[]]) + ([+[]])

Breaking this down,we can simplify by observing that +[] evaluates to 0. To satisfy yourself why this is true, check out the unary + operator and follow the slightly tortuous trail which ends up with ToPrimitive converting the empty array into an empty string, which is then finally converted to 0 by ToNumber. We can now substitute 0 for each instance of +[]:

(++[[]][0]) + [0]

Now we’re getting somewhere. So what about that ++[[]][0]? Well, that’s a combination of the prefix increment operator (++), an array literal defining an array with single element that is itself an empty array ([[]]) and a property accessor ([0]) called on the array defined by the array literal.

So, we can simplify [[]][0] to just [] and we have ++[], right? In fact, this is not the case: evaluating ++[] throws an error, which may initially seem confusing. However, a little thought about the nature of ++ makes this clear: it’s used to increment a variable (e.g. ++i) or an object property (e.g. ++obj.count). Not only does it evaluate to a value, it also stores that value somewhere. In the case of ++[], it has nowhere to put the new value (whatever it may be) because there is no reference to an object property or variable to update. In spec terms, this is covered by the internal PutValue operation, which is called by the prefix increment operator.

So then, what does ++[[]][0] do? Well, by similar logic as +[], the empty array that is the value of property 0 in the outer array is converted to 0 and this value is incremented by 1 to give us a final value of 1. The value of property 0 in the outer array is updated to 1 and the whole expression evaluates to 1.

This leaves us with

1 + [0]

… which is a relatively simple use of the addition operator. Both operands are first converted to primitives and if either primitive value is a string, string concatenation is performed, otherwise numeric addition is performed. [0] converts to “0″, so string concatenation is used, producing “10″.

As a final aside, something that may not be immediately apparent is that overriding either one of the toString() or valueOf() methods of Array.prototype will change the result of the expression, because both are checked and used if present when converting an object into a primitive value. For example, the following

Array.prototype.toString = function() {
  return "foo";
};
++[[]][+[]]+[+[]]

… produces “NaNfoo”. Why this happens is left as an exercise for the reader…

One thought on “Why ++[[]][+[]]+[+[]] evaluates to “10″ in JavaScript

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>