Почему ++[[]][+[]]+[+[]] возвращает строку "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, и комбинируя такие конструкции можно получить любые числа и строки.
Ответов пока нет.
Войдите чтобы оставить ответ