При чтении этой статьи, размещенной на 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.
То, что я нахожу самым загадочным, - это эта часть: [][[]]