Подтвердить что ты не робот

Почему в JavaScript существует "" == [null] true?

Я знаю, что JavaScript имеет множество безумных результатов при сравнении типов, хотя я не совсем понимаю, почему. Сегодня наступил этот.

Почему

"" == [null]

оценить true в JavaScript?

Еще некоторое удовольствие от Javascript, благодаря @Qantas:

4b9b3361

Ответ 1

"Алгоритм сравнения абстрактного равенства" имеет много частей, но здесь важно следующее:

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

(Это тоже зеркальное изображение). Итак, поскольку "" - это строка, а [null] - это объект, мы должны сначала преобразовать [null] в строку, вызвав ToPrimitive([null]). Это внутренняя операция, описанная ниже, когда она попросила преобразовать экземпляр объекта в примитивное значение:

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

Теперь внутренняя операция [[DefaultValue]] вызовет .toString() объекта и вернет это значение. Попробуйте [null].toString() в консоли браузера:

> [null].toString()
""

И там у вас есть.

Изменить: И почему [null].toString() пустая строка? Поскольку операция .toString() в экземплярах Array всегда просто вызывает .join() и всегда дает пустую строку для значений null и undefined. Таким образом, массив из одного null заканчивается как одна пустая строка.

Ответ 2

Это согласно тайному типу-преобразованию правил Javascript. Правило № 8:

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

Итак, сравнение между x = "" и y = [null] преобразуется в строку с помощью ToPrimitive. Преобразование массива с одним пустым элементом приводит к пустой строке (потому что Array.toString() возвращает список значений, разделенных запятыми), поэтому они оценивают равны.

Ответ 3

Почему "" == [null] оценивается как true?

Потому что вы сравниваете массив со строкой, используя нестрогий оператор равенства == - поэтому он попытается использовать значения до того же типа перед их сопоставлением.

Что происходит в деталях:

  • вы сравниваете строку с объектом, поэтому объект передается в строку:
  • Когда массив передается в примитивное значение, он вызывается методом .toString() (как подробно объясняется другими ответами), что эквивалентно вызову .join():
  • который в случае одноэлементного массива, который содержит только undefined или null значение возвращает пустую строку
  • который, наконец, эквивалентен пустой строке

Этот третий шаг является неожиданным ([null]+"" != null+""), если он действительно передал это строке, результат был бы "null", а ваше равенство было бы ложным.

Ответ 4

Посмотрите на спецификацию и выполните каждый шаг

Переход через Алгоритм сравнения равенства (§11.9.3):

  • typeof ""; // string и typeof [null]; // object поэтому неприменимо
  • нет null или undefined, поэтому неприменимо
  • то же, что и 2
  • не является числом, не применимым
  • так же, как 4
  • не является bool, не применимо
  • снова не применимо
  • наконец, что-то применимое, теперь нам нужно знать ToPrimitive([null])

§9.1 ToPrimitive для объектов говорит, что нам нужно работать [[DefaultValue]] (§8.12.8), точки 1 и 2 из которых говорят, что если вы можете сделать .toString, и он дает строку, верните ее, поэтому

[null].toString(); // ""

Итак, теперь мы выполняем сравнение "" == "", которое true с помощью пункта 1 алгоритма сравнения абстрактного равенства. d.

Если Type(x) является строкой, верните true, если x и y - это точно такая же последовательность символов (одинаковая длина и одинаковые символы в соответствующих позициях). В противном случае верните false.

Ответ 5

JavaScript слабо типизирован; вы можете использовать следующее для получения ложного результата:

"" === [null]

Ответ 6

Значение null - это литерал JavaScript, представляющий значение null или "пустое" значение, то есть нет значения объекта. Это одно из базовых значений JavaScript.

Значение null является литералом (не может быть свойство глобального объекта, такого как undefined). В API-интерфейсах нуль часто извлекается на месте, где можно ожидать объекта, но не относится к объекту. При проверке нулевого или undefined остерегайтесь различий между операторами равенства (==) и identity (===) (преобразование типа выполняется с помощью первого).

typeof null        // object (bug in ECMAScript, should be null)
typeof undefined   // undefined
null === undefined // false
null  == undefined // true