Question

Why `++[[]][+[]] + [+[]]` Returns "10" in JavaScript

javascriptsyntaxjsfuck

Question

In JavaScript, the following expression is valid and returns the string "10":

console.log(++[[]][+[]] + [+[]])

Why does this happen? What steps does JavaScript follow to evaluate this expression, and how do array access, unary +, prefix increment ++, and type coercion combine to produce the final string result?

Short Answer

By the end of this page, you will understand how JavaScript evaluates ++[[]][+[]] + [+[]] step by step. You will learn how empty arrays are converted to numbers and strings, how +[] becomes 0, how [[]][0] resolves to an empty array, how prefix increment triggers numeric coercion, and why the final + performs string concatenation instead of numeric addition.

Concept

JavaScript allows many implicit type conversions. This is called type coercion. The expression

++[[]][+[]] + [+[]]

looks strange, but it is built from a few normal rules:

  • +value tries to convert value to a number.
  • array[index] accesses an element in an array.
  • ++value converts value to a number, adds 1, and returns the incremented value.
  • a + b does either numeric addition or string concatenation, depending on the types after conversion.

The reason this matters is that JavaScript code often interacts with values from forms, APIs, query strings, configuration files, and user input. Those values may not already be in the type you expect. Understanding coercion helps you read unusual code, debug bugs, and avoid surprising behavior.

In this expression, the final result is "10" because:

  1. +[] becomes 0.
  2. [[]][0] gives [].
  3. ++[] converts [] to 0, increments it to 1.
  4. The right side [+[]] becomes [0].
  5. During 1 + [0], the array [0] becomes the string "0".
  6. Then 1 + "0" becomes the string "10".

So the final result is not the number 10, but the string "10".

Mental Model

Think of JavaScript like a cashier who keeps converting items into a format it can work with.

  • +[] is like asking, "Can this empty array be treated as a number?" JavaScript says: yes, that becomes 0.
  • [[]][0] is like opening a box and taking out the first item. The outer array contains one item: an empty array.
  • ++ is like saying, "Turn this into a number and add one."
  • The final + is tricky: if one side turns into a string, JavaScript switches from math mode to joining text mode.

So the expression is basically:

  • get an empty array
  • turn it into 0
  • increment it to 1
  • take another array that becomes "0"
  • join 1 and "0"
  • result: "10"

A useful shortcut is: arrays often become strings first, and strings strongly influence the + operator.

Take Quiz

Syntax and Examples

Here are the key pieces of syntax involved.

1. Unary plus converts to number

console.log(+[]);   // 0
console.log(+"5"); // 5
console.log(+true); // 1

+value tries to convert the value into a number.

  • [] becomes "" when converted to a primitive string-like value
  • Number("") is 0
  • so +[] is 0

2. Array indexing

const outer = [[]];
console.log(outer[0]); // []

The array [[]] contains one element, which is [].

3. Prefix increment

let x = [];
console.log(++x); // 1

Why?

  • x is []
  • ++x converts x to a number
  • [] becomes 0
  • increment gives 1

4. + can concatenate strings

console.log(1 + [0]); // "10"

Why?

  • [0] becomes "0"
  • 1 + "0" is string concatenation
  • result: "10"

Putting it together

console.log(++[[]][+[]] + [+[]]); // "10"

Breakdown:

+[]      // 0
[[]][0]  // []
++[]     // 1
[+[]]    // [0]
1 + [0]  // "10"

This works because JavaScript performs several automatic conversions along the way.

Step by Step Execution

Let us trace a simpler rewritten version of the expression.

const left = ++[[]][+[]];
const right = [+[]];
const result = left + right;
console.log(result);

Step 1: Evaluate +[]

+[]
  • [] is an empty array
  • unary + converts it to a number
  • empty array becomes ""
  • Number("") is 0

So:

+[] // 0

Step 2: Evaluate [[]][+[]]

Now substitute the 0:

[[]][0]
  • [[]] is an array with one element
  • that one element is []
  • index 0 returns the first element

So:

[[]][0] // []

Step 3: Evaluate ++[[]][+[]]

Now we have:

++[]

The prefix increment does numeric conversion:

  • [] becomes 0
  • increment gives 1

So the left side becomes:

++[[]][+[]] // 1

Step 4: Evaluate [+[]]

Inside the array:

+[] // 0

So:

[+[]] // [0]

Step 5: Evaluate 1 + [0]

This is the most important part.

1 + [0]

For +, JavaScript checks whether string concatenation should happen.

  • [0] converts to the string "0"
  • now the expression is:
1 + "0"

When one side is a string, + concatenates:

"10"

Final result

console.log(++[[]][+[]] + [+[]]); // "10"

Real World Use Cases

You probably should not write code like this in production, but the concepts behind it are very important.

1. Handling form input

Form fields often give you strings, even when the user typed a number.

const age = "42";
console.log(+age + 1); // 43

Understanding numeric conversion prevents accidental string concatenation.

2. Parsing API values

APIs may return values in mixed formats.

const price = "19.99";
const quantity = "2";
console.log(+price * +quantity); // 39.98

3. Debugging coercion bugs

A common bug is expecting math but getting strings.

console.log(1 + "2"); // "12"
console.log(1 + 2);   // 3

Knowing how + behaves helps you find these issues quickly.

4. Working with arrays in logs or output

Arrays often convert to strings in surprising ways.

console.log([1, 2, 3] + ""); // "1,2,3"
console.log([] + "");        // ""

5. Reading legacy or code-golf style JavaScript

You may encounter heavily compressed expressions in old code, interviews, puzzles, or minified snippets. Even if you would never write them yourself, understanding coercion makes them readable.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid relying on surprising coercion. But they do use the underlying ideas in safer ways.

Explicit conversion

Instead of writing +value everywhere, many teams prefer clearer code:

const count = Number(inputValue);

This makes intent obvious.

Guard clauses for invalid numbers

const amount = Number(userInput);
if (Number.isNaN(amount)) {
  throw new Error("Amount must be a valid number");
}

Validation before arithmetic

function addToCartQuantity(currentQty, incomingQty) {
  const current = Number(currentQty);
  const incoming = Number(incomingQty);

  if (Number.isNaN(current) || Number.isNaN(incoming)) {
    return currentQty;
  }

  return current + incoming;
}

Avoiding accidental string concatenation

const total = Number(subtotal) + Number(tax);

This is safer than:

const total = subtotal + tax;

if either value might be a string.

Logging and serialization

Developers often use JSON.stringify() instead of implicit array-to-string conversion:

console.log(JSON.stringify([0])); // "[0]"

This avoids confusion between [0] and "0".

Code review guidance

A common team rule is:

  • avoid clever coercion unless it is very clear
  • prefer explicit conversion when readability matters
  • never depend on obscure behavior for core business logic

Common Mistakes

1. Confusing numeric addition with string concatenation

Broken example:

console.log(1 + "2"); // "12"

Why it happens:

  • one operand is a string
  • + switches to concatenation

Safer version:

console.log(1 + Number("2")); // 3

2. Assuming arrays behave like numbers

Broken example:

console.log([1] + 1); // "11"

Why it happens:

  • [1] becomes "1"
  • then string concatenation happens

3. Forgetting that [] can become 0

console.log(+[]); // 0
console.log(Number([])); // 0

This surprises many beginners because an empty array does not look numeric.

4. Writing clever code that is hard to maintain

Avoid code like:

const value = ++[[]][+[]] + [+[]];

Prefer clear code:

const first = [[]][0];
const incremented = Number(first) + 1;
const result = String(incremented) + String([0]);

5. Expecting all arrays to become useful numbers

Broken example:

console.log(+[1, 2]); // NaN

Why?

  • [1, 2] becomes the string "1,2"
  • Number("1,2") is NaN

6. Not knowing the difference between prefix and postfix increment

let x = 0;
console.log(++x); // 1

let y = 0;
console.log(y++); // 0
console.log(y);   // 1

Prefix returns the incremented value immediately. Postfix returns the old value first.

Comparisons

Related coercion behaviors

ExpressionResultWhy
+[]0Empty array becomes empty string, then number 0
+""0Empty string converts to 0
+true1Boolean true converts to 1
[] + []""Both arrays become empty strings
[] + {}"[object Object]"Array becomes "", object becomes string
[0] + 1"01"[0] becomes string "0", then concatenation
1 + [0]"10"[0] becomes string "0", then concatenation
Number([])0Explicit numeric conversion
String([0])"0"Array stringifies to its elements joined by commas

+ operator: addition vs concatenation

CaseBehavior
Both operands are numeric after conversionNumeric addition
One operand becomes a stringString concatenation

Examples:

console.log(1 + 2);      // 3
console.log("1" + 2);    // "12"
console.log(1 + [2]);    // "12"
console.log(1 + Number([2])); // 3

Prefix ++ vs unary +

OperatorPurpose
+valueConvert to number
++valueConvert to number, add 1, return new value

Example:

console.log(+[]);  // 0
let x = [];
console.log(++x);  // 1
Take Quiz

Cheat Sheet

Quick reference

Unary plus

+value
  • Converts value to a number
  • +[] -> 0
  • +"5" -> 5
  • +true -> 1

Prefix increment

++value
  • Converts value to a number
  • Adds 1
  • Returns the new value

Array indexing

array[index]
  • [[]][0] -> []

Array to string conversion

String([])    // ""
String([0])   // "0"
String([1,2]) // "1,2"

+ operator rules

a + b
  • numeric addition if both sides are numbers
  • string concatenation if one side is a string after conversion

The full expression

++[[]][+[]] + [+[]]

Becomes:

++[[]][0] + [0]
++[] + [0]
1 + [0]
1 + "0"
"10"

Important edge cases

+[]      // 0
+{}      // NaN
+[1]     // 1
+[1, 2]  // NaN
[] + []  // ""
[] + 1   // "1"
1 + []   // "1"

FAQ

Why does +[] equal 0 in JavaScript?

Because unary + converts its operand to a number. An empty array becomes an empty string "", and Number("") is 0.

Why does [0] become "0"?

Arrays convert to strings by joining their elements with commas. A one-element array [0] becomes the string "0".

Why is the final result a string instead of a number?

Because the right side [+[]] becomes [0], which converts to "0" during +. Then 1 + "0" performs string concatenation, producing "10".

Does ++[] really work in JavaScript?

In an expression like this, yes. The value is coerced to a number, so [] becomes 0, then incremented to 1.

Is this behavior specific to JavaScript?

Yes. JavaScript has unusual coercion rules compared with many other languages. Similar-looking expressions may fail or behave differently elsewhere.

Should I use expressions like this in real code?

Usually no. They are legal, but they hurt readability. Prefer explicit conversions like Number(value) and clear variable names.

What is the safest way to avoid coercion surprises?

Use explicit conversion, such as Number(value) or String(value), and check values with Number.isNaN() when needed.

Take Quiz

Mini Project

Description

Build a small JavaScript coercion explorer that prints the result of unusual expressions and explains their types. This helps you practice how arrays, strings, numbers, and operators interact in JavaScript.

Goal

Create a script that evaluates several coercion examples and shows both the result and the resulting type.

Requirements

  1. Create a function that logs an expression label, its result, and typeof the result.
  2. Test at least five expressions involving arrays, unary +, or string concatenation.
  3. Include the expression ++[[]][+[]] + [+[]].
  4. Show at least one example that returns a number and one that returns a string.
Take Quiz

Keep learning

Related questions

View more