Avatar ·

Почему ++[[]][+[]]+[+[]] возвращает строку "10" в JavaScript?

Всем привет! Я изучаю JavaScript и наткнулся на очень странный код. В одной статье увидел такое выражение: ```javascript console.log(++[[]][+[]]+[+[]]); // Выводит "10" ``` Я вообще не понимаю, как это работает. Почему массив, плюс плюс, пустой массив в квадратных скобках и плюс пустой массив дают строку "10"? Я знаю, что в JS есть приведение типов, но это выглядит как какая-то магия. Я попытался разобрать это по частям, но запутался ещё больше. Например, что значит `++[[]]`? Или `+[]`? Как из всего этого получается именно "10", а не что-то другое? Может кто-нибудь объяснить по шагам, что именно происходит в этом выражении? Буду очень благодарен за подробное объяснение, потому что я хочу понять, как работают операторы и приведение типов в JavaScript на глубоком уровне. Спасибо! <<>>

Разбор выражения ++[[]][+[]]+[+[]] по шагам

Это классический пример, демонстрирующий работу приведения типов и операторов в JavaScript. Давайте разберём его по частям.

Выражение состоит из двух частей, соединённых оператором +:

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

Разобьём на шаги:

Шаг 1: Разбираем правую часть [+[]]

Начнём с самого простого — +[]:

  • [] — пустой массив
  • Унарный плюс + преобразует его в число: +[] → 0
  • Значит [+[]] = [0] — массив с одним элементом 0

Шаг 2: Разбираем левую часть ++[[]][+[]]

Здесь есть конструкция [[]][+[]]:

  • [[]] — это массив, содержащий один элемент — пустой массив (назовём его внешним массивом)
  • [+[]] — это индекс для доступа к элементу. Как мы уже знаем, +[] = 0
  • Значит [[]][0] — получаем первый (нулевой) элемент внешнего массива, то есть пустой массив []

Теперь у нас есть ++[]:

  • Оператор ++ (префиксный инкремент) сначала преобразует операнд в число, затем увеличивает на 1 и возвращает результат
  • Пустой массив [] преобразуется в число: Number([]) → 0
  • Затем 0 + 1 = 1
  • Итак, ++[[]][+[]] возвращает число 1

Шаг 3: Собираем всё вместе

Теперь у нас есть:

1 + [0]

Оператор + между числом и массивом:

  • Если один из операндов — строка, то оба преобразуются в строки
  • Массив [0] преобразуется в строку: [0].toString() → "0"
  • Число 1 преобразуется в строку: "1"
  • Конкатенация: "1" + "0" = "10"

Почему именно так работает приведение типов?

Ключевые моменты:

  • Унарный плюс (+) преобразует значение в число: +[] → 0, +"5" → 5
  • Префиксный инкремент (++) сначала преобразует операнд в число, потом увеличивает
  • Бинарный плюс (+) между разными типами: если один операнд строка, то оба становятся строками
  • Массивы при преобразовании в строку дают элементы, разделённые запятыми: [1,2,3].toString() → "1,2,3", а пустой массив — пустую строку

Это выражение — отличный тест на понимание системы типов JavaScript. В реальном коде так писать не стоит, но знать механизмы полезно.

<<>>

Альтернативный взгляд: разбор через эквивалентные преобразования

Можно переписать это выражение через временные переменные, чтобы было нагляднее:

// Исходное выражение:
// ++[[]][+[]] + [+[]]

// Раскладываем:
let outerArray = [[]];        // Массив, содержащий пустой массив
let index = +[];              // 0 (унарный плюс преобразует [] в 0)
let innerArray = outerArray[index]; // Получаем пустой массив []
let incremented = ++innerArray;     // Преобразуем [] в 0, затем +1 = 1
let rightPart = [+[]];        // Массив с элементом 0
let result = incremented + rightPart; // 1 + [0] → "1" + "0" = "10"

console.log(result); // "10"

Обратите внимание: ++ не только возвращает новое значение, но и изменяет исходный массив (если это возможно). В данном случае ++[] работает, потому что пустой массив приводится к числу, но сам массив не изменяется (примитивное преобразование).

Этот пример часто используется в JSFuck — эзотерическом стиле программирования, где код пишется только с использованием 6 символов: []()!+. Выражение +[] даёт 0, +!![] даёт 1, и комбинируя такие конструкции можно получить любые числа и строки.