Javascript очевидное безумие [дубликат]

Возможное дублирование:
Конфликт логических значений пустого массива JavaScript

В чем причина того, что

<code>[ ([] == false), ([] ? 1 : 2) ]
</code>

возвраты[true, 1]?

Другими словами, пустой список логически верен в логическом контексте, но равенfalse.

Я знаю, что с помощью=== решает проблему, но чем объясняется этот, по-видимому, совершенно нелогичный выбор?

Другими словами, считается ли это ошибкой в языке, чем-то непреднамеренным, которое только что произошло, и это не может быть исправлено, потому что уже слишком поздно или действительно в дизайне языка кто-то думал, что это круто, иметь такое явное безумие, что я ' я уверен, что это сбивает с толку многих программистов?

Техническое объяснение того, как это происходит, в то же время удивительно и страшно, однако меня больше интересовало, что стоит за этим дизайном.

Редактироват

Я принял очень подробное объяснение Ника Реталлака, даже если оно касается только технических причин того, почему[]==false верно: на удивление, это происходит потому, что[], преобразованный в строку, является пустой строкой, а числовое значение пустой строки специально обрабатывается как 0 вместо явно более логичногоNaN. С пустым объектом например сравнение({}) == false возвращает false, потому что строковое представление пустого объекта не является пустой строкой.

Мое любопытство до сих пор остается о том, что все это просто непредвиденно (и теперь, к сожалению, закреплено стандартом).

 Elliot Bonneville11 мая 2012 г., 19:44
![] == false возвращаетtrue слишком. : -)
 user115052511 мая 2012 г., 19:33
 dmp11 мая 2012 г., 19:33
это смешно! []. Может быть, проблема String ()?
 user115052511 мая 2012 г., 19:56
@ ElliotBonneville еще одна забавная вещь:![].toString() == false возвращаетfalse.

Ответы на вопрос(2)

которое (вопреки распространенному мнению) не совпадает с== false.

Falsy на самом деле ссылается на значение, которое имеет логический эквивалент false, а не на выражение, результат которого == false. Единственные значения Falsy в JavaScript:false, 0, "", null, undefined, а такжеNaN. Таким образом, любое из этих значений - или любое выражение, которое переводится в одно из этих значений (как вif утверждение или использование тернарного оператора) - ложь.

Вот таблица, которую я собрал из ложных / истинных значений в JavaScript, которые должны помочь объяснить всю эту проблему.http: //jsfiddle.net/philipwalton/QjSYG

 jmar77711 мая 2012 г., 19:40
Отличный стол! Однако стоит отметить, что путаница здесь, по-видимому, связана с тем фактом, что[] == false оценивается как ложное, потому что это то же самое, что и[].toString() == false, так что в конечном итоге это'' == false.
 Philip Walton11 мая 2012 г., 20:05
@ jmar777 ты уверен? Если я бегу[] === "" в консоли я получаю ложь, так как же[] быть таким же, как[].toString(). Можете ли вы привести что-то, показывающее, что[] == false эквивалентно[].toString == false
 jbabey11 мая 2012 г., 19:34
потрясающая скрипка.
 jmar77711 мая 2012 г., 20:09
@ Филипп разница в=== против==. Когда вы просто используете двойное равенство, приведение типа допускается. Что технически происходит (с==) это движок JavaScript говорит "это[] равно''? ". Ответ, очевидно, нет, поэтому он говорит:" Хорошо, позвольте мне попробовать с некоторым типом принуждения ... ". Вопрос сейчас" это'' равно''? ", что теперь верно. Когда вы используете=== оператор, однако, второй шаг никогда не происходит, следовательно, он оценивается как ложный.
 jmar77711 мая 2012 г., 20:12
Вы можете прочитать о том, как это работает здесь: Developer.mozilla.org / о / JavaScript / Справочник / Операторы / .... В частности, «... если один из операндов является строкой, другой операнд преобразуется в строку, если это возможно».
Решение Вопроса

ECMAScript Стандарт 262.

Выражение[] ? 1 : 2 очень просто:

11.12 Условный оператор (?:)

Пусть это будет результат оценки LogicalORExpression.ЕслиToBoolean (ПолучитьЗначение (LRef)) верно, тогда Пусть trueRef будет результатом вычисления первого AssignmentExpression.Return GetValue (trueRef). Else Пусть falseRef будет результатом вычисления второго AssignmentExpression.Return GetValue (falseRef)

9.2 ToBoolean

Не определено: ложьNull: ложьBoolean: результат равен входному аргументу (без преобразования).Number: результат равен false, если аргумент равен +0, 0 или NaN; в противном случае результат верен.String: результат равен false, если аргумент является пустой строкой (ее длина равна нулю); в противном случае результат верен. Объект: правда

Так что это правда.

Теперь о том, что происходит, когда вы используете оператор двойного равенства. Возможно, это поможет объяснить, почему вы никогда не должны этого делать.

Поведение == объясняется в разделе 11.9.3: Алгоритм сравнения абстрактного равенства.

Для x == y, где x = [] и y = false, это происходит:

11.9.3: Алгоритм сравнения абстрактного равенства

Если тип (y) является логическим, возвращает результат сравнения x == ToNumber (y)

9.3 ToNumber

Результат + 0 если аргументложны.

Теперь у нас есть [] == 0

11.9.3: Алгоритм сравнения абстрактного равенства

Если Type (x) равен Object, а Type (y) равен String или Number, возвращает результат сравненияToPrimitive (x) == y.

9.1 ToPrimitive

Возвращает значение по умолчанию для объекта. Значение объекта по умолчанию извлекается путем вызова[[Значение по умолчанию] внутренний метод объекта, передавая необязательную подсказку PreferredType. Поведение внутреннего метода [[DefaultValue]] определяется этой спецификацией для всех собственных объектов ECMAScript в 8.12.8.

8.12.8 DefaultValue:

Когда внутренний метод [[DefaultValue]] для O вызывается без подсказки, он ведет себя так, как если бы подсказка былаЧисл

Пусть valueOf будет результатом вызова внутреннего метода [[Get]] объекта O с аргументом "valueOf". Если IsCallable (valueOf) равно true, тоLet val будет результатом вызова внутреннего метода [[Call]] для valueOf, с O в качестве значения this и пустым списком аргументов. Если val - примитивное значение, вернуть valLet toString будет результатом вызова внутреннего метода [[Get]] объекта O с аргументом "toString". Если IsCallable (toString) равен true, то Пусть str будет результатом вызова внутреннего метода [[Call]] длянанизыват, с O в качестве значения this и пустым списком аргументов. Если str является примитивным значением, возвращение ул.

Я предполагаю, что эта попытка сначала выполняется с помощью valueOf, а затем отклоняет его, поскольку в результате получается тот же массив, с которого вы начали. Затем он вызывает toString для Array, который представляется универсально реализованным в виде списка значений, разделенных запятыми. Для пустых массивов, подобных этому, это приводит к пустой строке.

Теперь у нас есть '' == 0

11.9.3: Алгоритм сравнения абстрактного равенства

Если Type (x) равен String, а Type (y) равен Number, вернуть результат сравненияToNumber (x) == y

9.3.1 ToNumber, примененный к строковому типу

StringNumericLiteral, который являетсяempty или содержит только пробел преобразуется в + 0.

Теперь у нас 0 == 0

11.9.3: Алгоритм сравнения абстрактного равенства

Если x - это то же числовое значение, что и y, вернуть true

Потрясающе. Это верно. Довольно запутанный способ добраться сюда.

 jmar77711 мая 2012 г., 21:08
Это впечатляющий ответ.
 user115052511 мая 2012 г., 19:55
Кто-то прочитал ссылку в моем комментарии: D.
 user115052511 мая 2012 г., 21:11
@ NickRetallack вы редактировали свой ответ довольно часто, в начале он был очень похож на ссылку Forums.whirlpool.net.au / архив / 966449 # r15310322 в моем комментарии. Конечно, ваш ответ теперь гораздо более подробный.
 Nick Retallack11 мая 2012 г., 21:08
@ BenniKa какой комментарий?

Ваш ответ на вопрос