При чтении этой статьи, размещенной на dzone, я нашел фрагмент JavaScript, первоначально размещенный в Twitter Маркусом Лагергеном.
Следующий код, по-видимому, печатает строку "fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
Это подразумевает неявное кастинг типов, и я пытаюсь понять, как именно эта строка интерпретируется.
Я выделил каждый символ
-
(![]+[])[+[]]prints"f" -
(![]+[])[+!+[]]печатает"a" -
([![]]+[][[]])[+!+[]+[+[]]]печатает"i" -
(![]+[])[!+[]+!+[]]prints"l"
Мне также удалось сломать выражения, возвращающие каждую букву, кроме "i"
письмо "f"
![] пустой массив - это объект, который согласно документации ECMAScript, пункт 9.2, оценивается до true при преобразовании в boolean, так что это false
false+[] в соответствии с пунктом 11.6.1 оба аргумента двоичного оператора + преобразуются в String, поэтому мы получаем "false"+"", который оценивает "false"
+[] Унарный оператор plus вызывает преобразование ToNumber, за которым следует преобразование ToPrimitive, если аргумент равен Object. Результат такого преобразования определяется вызовом внутреннего метода [[DefaultValue]] объекта. В случае пустого массива он по умолчанию равен 0.
(Документация ECMAScript, разделы: 11.4.6, 9.3, 9.1)
"false"[0] мы обращаемся к символу с индексом 0, поэтому "f"
письмо "a"
В той же истории единственная разница здесь - это дополнительные преобразования в части в квадратных скобках (которая вычисляет число, указывающее на другой символ в строке "false"), вызванный использованием унарных + и ! операторов.
+[] оценивается как 0, как описано выше.
!0 оценивается как true, как определено в разделе Раздел 9.2 и Раздел 11.4.9. Во-первых, 0 преобразуется в boolean false, а затем оператор инвертирует значение.
+true снова, унарный плюс запускает преобразование ToNumber, которое возвращает 1 для двоичного true
(раздел 11.4.6 и 9.3)
"false"[1] возвращает второй символ в строке, который равен "a"
буква "l"
!+[] оценивается как true, как описано выше
true+true, используя двоичный + для примитивов, запускает преобразование ToNumber. В случае истины его результат равен 1 и 1+1 равен 2
"false"[2] - самоочевидный
письмо "i"
Что оставляет меня в тупике - это письмо "i". Я вижу, что вторая часть (в квадратных скобках) оценивает строку "10" и что первая часть (в круглых скобках) возвращает "falseundefined", но Я не могу делать головы или хвосты того, как это происходит. Может кто-нибудь объяснить это шаг за шагом? Особенно волшебство, которое случается с квадратными скобками? (массивы и доступ к массиву)
Если возможно, я хотел бы, чтобы каждый шаг содержал ссылку на основные правила ECMAScript.
То, что я нахожу самым загадочным, - это эта часть: [][[]]