(! [] + []) [+ []]… Объясните, почему это работает

107
alert((![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]);

Выходной сигнал этого кода: fail. Зачем?

Кстати, (![]+[])[+!+[]] == 'false'[1]да ?. Но почему ![]+[] == "false"и почему +!+[] == 1?

cdxf
источник
14
@Snoob Я тебе не доверяю. В конце концов, это бомба-вилка.
Йоханнес Шауб - лит
3
Конечно, это строковый литерал;)
Йи Цзян
3
(![]+[])[+[]]это «f» (первый символ от «false»), (![]+[])[+!+[]]это «a» и т. д.
Маурисио Схеффер
3
@Snoob: как вы сказали, вы можете протестировать каждое выражение в своем браузере. alert(![]+[])Тогда попробуйте, alert(+!+[])и вы увидите.
Маурисио Схеффер,
12
Бесполезно это или нет, но я считаю это интересным вопросом и хотел бы увидеть хорошо сформулированное объяснение. Многие гольф-поля Code были бы закрыты, если бы рассматривались их полезность или практичность. Упражнения и игры полезны сами по себе для расширения ума и мыслительного процесса.
John K

Ответы:

127

Как прокомментировал @Mauricio, (![]+[])[+[]]это «f» (первый символ «false»), (![]+[])[+!+[]])это «a» и т. Д.

Как это работает?

Давайте рассмотрим первый символ, "f":

(![]+[])[+[]]; // 'f'

Первая часть выражения, заключенная в круглые скобки, состоит ![]+[]из первого операнда оператора сложения , и ![]он будет порождать false, потому что объект массива - как и любой другой экземпляр объекта - является правдивым , и применение логического (!) НЕ унарного оператор, он false, например , выдает значение .

![]; // false, it was truthy
!{}; // false, it was truthy
!0;  // true, it was falsey
!NaN;  // true, it was falsey

После него у нас есть второй операнд добавления, пустой массив, []это сделано только для преобразования falseзначения в String, потому что строковое представление пустого массива является просто пустой строкой, что эквивалентно:

false+[]; // "false"
false+''; // "false"

Последняя часть, пара квадратных скобок после скобок, они являются средством доступа к свойствам, и они получают выражение, которое формируется оператором Unary Plus, снова применяемым к пустому массиву.

Оператор Unary Plus выполняет преобразование типов Number, например, в:

typeof +"20"; // "number"

Еще раз, это применяется к пустому массиву, и, как я сказал ранее, строковое представление массива является пустой строкой, и когда вы конвертируете пустую строку в Number, она преобразуется в ноль:

+[]; // 0, because
+[].toString(); // 0, because
+""; // 0

Поэтому мы можем «декодировать» выражение в несколько шагов:

(![]+[])[+[]];
(false+[])[+[]];
(false+'')[+[]];
(false+'')[0];
('false')[0];  // "f"

Обратите внимание, что доступ к символам с использованием обозначения скобок для значений String не был частью ECMAScript 3rd. Спецификация издания, (поэтому charAtметод и существовал).

Однако такого рода «свойства индекса», представляющие символы строки, были стандартизированы в ECMAScript 5, и даже до стандартизации эта функция была доступна в большом количестве браузеров (даже в IE8 (стандартный режим)).

CMS
источник
46
Надеюсь, это никогда не вопрос интервью.
Inisheer
4
@JTA: Я надеюсь, что это так ! Я бы сдал :-D
Маурисио Шеффер
18
Откуда взялось «i»?
Джош Стодола,
5
@rlemon, в языке нет intтипа данных, на самом деле все числа имеют 64-битный формат двойной точности (значения IEEE 754), хотя некоторые операторы внутренне работают с целочисленными значениями (например, побитовые операторы), результат всегда двойной . В 'i'этом примере undefined, но он может быть получен, Infinityнапример: (+!+[]/+[+[]]+[])[!+[]+!+[]+!+[]]=> (1/0+'')[3]=> (Infinity+'')[3]=>'i'
CMS
5
@JoshStodola Ну, ~ 3 месяца спустя, дальнейшее разъяснение. «I» в этом случае происходит от «undefined», да, но здесь есть еще одна хитрость. Код объединяет «false» в «undefined» для формирования "falseundefined"(построенного с использованием:), [![]]+[][[]]в котором индекс «i» равен 10. +!+[]+[+[]]дает "10". Это используется для извлечения «i» (строковые индексы можно использовать в javascript, если их можно явно привести к целым числам). Последняя конструкция, которая его производит:([![]]+[][[]])[+!+[]+[+[]]]
энтропия