Почему «,,,» == Array (4) в Javascript?

119

Загрузите свой интерпретатор / консоль и попробуйте сравнение

> ",,," == Array(4)
True

Зачем? Сначала я подумал, что, может быть, так как вы могли представить «,,,» как массив из четырех символов с завершающим срезом '\ 0', может быть, поэтому, но

> "..." == Array(4)

Возвращает «Ложь». Итак ... почему? Я знаю, что это какой-то своеобразный утиный ввод в Javascript, но мне просто любопытно, что подчеркивает такое поведение. Позаимствовал это из отличной презентации Зеда Шоу здесь, кстати .

ZenLikeThat
источник
14
Некоторые языки, кроме C, используют нулевое завершение так, чтобы это было видно программисту.
Joey
7
Если я могу спросить, что привело к этому открытию?
SomeKittens 05
1
@SomeKittens Зед Шоу прямо упоминает об этом в видео, на которое я ссылался в своем вопросе (как критика Javascript). Ура!
ZenLikeThat
5
@SomeKittens Это также упоминается в (довольно хорошо известно) «ВАТ» говорить, показывая некоторые причуды в Руби и JavaScript destroyallsoftware.com/talks/wat
Cronco
5
Это одна из многих веских причин всегда использовать ===вместо ==.
wprl

Ответы:

178

Поскольку правая операнд преобразуется в строку и строковое представление Array(4)является ,,,:

> Array(4).toString()
  ",,,"

Если вы используете функцию конструктора массива и передаете число, она устанавливает длину массива равной этому числу. Таким образом, вы можете сказать, что у вас есть четыре пустых индекса (таких же, как [,,,]), а строковое представление массивов по умолчанию - это список его элементов, разделенных запятыми:

> ['a','b','c'].toString()
  "a,b,c"

Как работает сравнение, описано в разделе 11.9.3 спецификации . Там вы увидите ( x == y):

8. Если Тип ( x ) - либо Строка, либо Число, а Тип ( y ) - это Объект,
вернуть результат сравнения x == ToPrimitive ( y ).

(массивы - это объекты в JavaScript)

и если вы последуете этому ToPrimitiveметоду, вы в конечном итоге обнаружите, что он вызывает toString.

Феликс Клинг
источник
2
Хорошо, теперь все это имеет для меня смысл. Спасибо.
ZenLikeThat 05
6
Что, в свою очередь, связано с тем, что массивы превращаются в строки, как если бы они использовали Array.join(",").
duskwuff -inactive- 05
Чтобы программировать на javascript, нужно быть чертовски терпеливым
matcheek
31

Внутренне это происходит

",,," == Array(4).toString()
Джейсон Кулатунга
источник
31

Попробуйте использовать ===. При использовании ==в Javascript он попытается преобразовать переменные, что приведет к подобным проблемам. Консоль преобразуется Array(4)в строковое представление (т.е. Array(4).toString), которое есть ",,,". Причина наличия запятых в том, что .toString()функция добавляет их к отдельным элементам в массиве.

См. Фрагмент ниже:

document.write( Array(4).toString() );

SomeKittens
источник
18

Это связано с тем, что Array(4)инициализирует массив из 4 пустых значений, ==неявно преобразует, поэтому:

 ",,," == Array(4)

 ",,," == Array(4).toString()

 ",,," == ["", "", "", ""] // note 3 commas for 4 values

 ",,," == ["", "", "", ""].toString()

Все похожи.

==выполняет неявное преобразование типов перед сравнением значений, что может привести к непредсказуемым результатам. Используйте ===для проверки типа и значения.

Кит
источник
5

Сравнение массива со строкой приводит к тому, что массив превращается в строку перед выполнением сравнения. Приведение пустого 4-элементного массива к строке дает именно эту строку.

Рассел Борогов
источник
4

Сначала я подумал, что это что-то с "прототипом" ... но после небольшого расследования я пришел к печальному выводу ...

По-видимому, это внутренняя и более непонятная js-штука с небольшой логикой ...

Просто попробуй

Array(4)==Array(4)

и никакого принуждения к типам тоже ...

Array(4)===Array(4)

и вы получите ЛОЖЬ

вы это знаете null==null, null===nullи даже undefined==undefinedи undefined===undefinedвозвращает ИСТИНА ... так что ... это немного непонятно ...

Array(4)==[,,,] также должно быть правдой

ZEE
источник
ZEE, Array (4) == [,,,] не будет правдой. Если мы сравним объект с примитивом, то объект будет преобразован в примитив. Вот почему он вызывает toString ().
девсатиш
array (x) должен быть адресом конструктора ... в любом случае, в системе (не беспокойтесь о том, какая система), <identity_X> === <identity_X> всегда может быть истинным!
ZEE