Приведение типов JavaScript со строками и индексированием

Почему в приведенном ниже фрагменте функция whatDoesItDo() возвращает «сбой» в виде строки? Было бы полезно, если бы кто-нибудь мог объяснить концепцию такого поведения.

function whatDoesItDo() {

  return (![] + [])[+[]] + (![] + [])[+!+[]] +
    ([![]] + [][
      []
    ])[+!+[] + [+[]]] + (![] + [])[!+[] + !+[]];

}

function result() {

  document.getElementById("result").innerHTML = whatDoesItDo();

}

result();
<html>

<body>
  <p id="result"></p>
</body>

</html>


person Flake    schedule 16.06.2015    source источник
comment
каков ваш ожидаемый результат?   -  person Ahosan Karim Asik    schedule 16.06.2015
comment
fail - это выход. Но вопрос в том, почему?   -  person Flake    schedule 16.06.2015
comment
Головоломки следует отправлять на codegolf.stackexchange.com.   -  person Dmitry Grigoryev    schedule 16.06.2015
comment
Если бы было проще искать такие вопросы. Подобные вопросы задавались слишком много раз.   -  person Felix Kling    schedule 16.06.2015
comment
@FelixKling: Может быть, нам следует добавить тег, например javascript-coercion-games, чтобы мы могли найти их позже. :-)   -  person T.J. Crowder    schedule 16.06.2015
comment
Я был в замешательстве относительно того, что искать в Google   -  person Flake    schedule 16.06.2015
comment
@T.J.Crowder: я добавил преобразование типов. По крайней мере сужает его.   -  person Felix Kling    schedule 16.06.2015
comment
@Flake: Да, очень сложно их искать.   -  person T.J. Crowder    schedule 16.06.2015
comment
@FelixKling: в итоге я назвал это js-type-coercion-puzzles. Посмотрим, выживет ли. :-)   -  person T.J. Crowder    schedule 16.06.2015


Ответы (1)


Вы видите эффекты A) приведения типов, B) индексации строк с использованием [] и C) конкатенации строк.

Давайте посмотрим на первый бит:

(![] + [])[+[]]

![] дает нам false, потому что [] является «истинным» значением, которое приводит к true при проверке как логическое значение, и поэтому ![] равно false.

Затем мы добавляем к нему [], что превращает их обоих в строки, потому что оператор + приводит оба своих аргумента к строкам, если какой-либо из них не является числом (если оба являются числами, он складывает), давая нам "false" (поскольку [].toString() равно [].join() что "").

Итак, теперь у нас есть "false".

Затем +[] равно 0, потому что он приводит пустой массив к числу, которое превращает его в строку (""), а +"" равно 0.

Наконец, это значение используется для "false": "false"[0] равно "f".

И так далее, все остальное — лишь вариации на эту тему. (!+[] равно true, что важно позже.)

person T.J. Crowder    schedule 16.06.2015
comment
Оператор '+' принимает два аргумента..... поэтому, если один из них равен 0, то что он принимает в качестве второго аргумента - person Flake; 16.06.2015
comment
@Flake Это не оператор сложения, это аннотация типа asm.js. - person Marko Gresak; 16.06.2015
comment
@Flake: в JavaScript (и в большинстве других языков программирования, синтаксически производных от языка B) есть два оператора +: унарный + (унарный = принимает один операнд) и binary + (binary = принимает два операнда). + в +[] является унарным +. В JavaScript практически единственная его задача — привести операнд к числу. - person T.J. Crowder; 16.06.2015
comment
Эта ссылка имеет хорошее объяснение для унарного + frontendplay.com/2013/05/25 /плюс-знак-javascript - person Flake; 17.06.2015
comment
@ T.J.Crowder Хорошо, я должен спросить - исключительно из любопытства, после того как нашел ваш вопрос в мета. Я получаю, что f, a и l происходят от приведения bool к строке и получения только n-го символа этой строки. Но откуда i? - person β.εηοιτ.βε; 25.06.2015
comment
@b.enoit.be [][[]] это [][""], что undefiнед :-) - person Lucas Trzesniewski; 25.06.2015
comment
@LucasTrzesniewski ах, да, умница, спасибо за свет. - person β.εηοιτ.βε; 25.06.2015
comment
@b.enoit.be: Что сказал Лукас. :-) В частности, ([![]] + [][[]]) становится falseundefined. Мы индексируем это с помощью +!+[] + [+[]], что в итоге становится "10". 11-й символ falseundefined — это i. - person T.J. Crowder; 25.06.2015