Может ли кто-нибудь объяснить, почему следующие два утверждения оцениваются как true?
[] == false
и
!![]
Этот вопрос исключительно из любопытства, почему это происходит, а не о том, как лучше всего проверить, является ли массив пустым.
Может ли кто-нибудь объяснить, почему следующие два утверждения оцениваются как true?
[] == false
и
!![]
Этот вопрос исключительно из любопытства, почему это происходит, а не о том, как лучше всего проверить, является ли массив пустым.
Первый:
[] == false
Оператор ==
выполняет преобразование типа в свои операнды, в этом случае обе стороны преобразуются в число, шаги, выполненные в алгоритме сравнения абстрактного равенства, будут быть:
В коде:
[] == 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.
См. также:
[] == 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, а затем инвертирует его, что приводит к ошибке.