Конфликтующие логические значения пустого массива JavaScript

Может ли кто-нибудь объяснить, почему следующие два утверждения оцениваются как true?

[] == false

и

!![]

Этот вопрос исключительно из любопытства, почему это происходит, а не о том, как лучше всего проверить, является ли массив пустым.

Ответ 1

Первый:

[] == false

Оператор == выполняет преобразование типа в свои операнды, в этом случае обе стороны преобразуются в число, шаги, выполненные в алгоритме сравнения абстрактного равенства, будут быть:

  • object == boolean
  • объект == номер
  • string == number
  • number == number

В коде:

[] == false; // convert false to Number
[] == 0;     // convert [] to Primitive (toString/valueOf)
"" == 0;     // convert "" to Number
0  == 0;     // end

Второе сравнение [] преобразуется в примитив, выполняются их методы valueOf и toString, но поскольку valueOf в объектах Array возвращает сам объект (наследуется от Object.prototype), тогда используется метод toString.

В конце, как вы видите, оба операнда преобразуются в число, и оба равны нулю, например:

Number([]) == 0;
Number(false) == 0;

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

[].toString(); // ""

И пустая строка, преобразованная в Number, возвращает ноль:

+""; // 0

Теперь двойное отрицание (!![]) производит true, потому что все экземпляры объекта являются правдивыми:

![];  // false, [] is truthy
!![]; // true, negation

Единственными значениями, которые являются ложными, являются:

  • null
  • undefined
  • 0
  • NaN
  • "" (пустая строка)
  • false

Все, что угодно, создаст true при преобразовании в Boolean.

См. также:

Ответ 2

[] == false

В этом случае тип левой стороны - это объект, тип правой части - логический. Когда объект сравнивается с (== The Abstract Equality Comparison), boolean, Javascript сначала преобразует логическое значение в число, получая 0. Затем он преобразует объект в "примитив", что дает пустую строку "". Затем он сравнивает пустую строку с 0. Пустая строка преобразуется в число, давая 0, которая численно равна 0 в правой части, поэтому результат всего выражения равен true.

Ref: http://es5.github.com/#x11.9.3 11.9.3 Алгоритм сравнения абстрактного равенства

!! []

В этом случае Javascript преобразует объект в логическое значение true, а затем инвертирует его, что приводит к ошибке.