Из консоли Google Chrome:
var x = null;
undefined
x > 0
false
x < 0
false
x > -1
true
x < 1
true
x == 1
false
x === 1
false
Из консоли Google Chrome:
var x = null;
undefined
x > 0
false
x < 0
false
x > -1
true
x < 1
true
x == 1
false
x === 1
false
Когда вы сравниваете значение null для равенства с 0, результат равен false. Если вы принудительно интерпретируете null
в числовом контексте, тогда он обрабатывается как 0, и результат становится истинным.
Вы можете заставить его быть числовым, поставив +
спереди или используя числовые операторы, такие как <
, <=
, >
и >=
. Обратите внимание на то, что null >= 0
и null <= 0
являются истинными.
> null == 0
false
> +null == 0
true
> null >= 0
true
> null <= 0
true
Спецификация языка ECMAScript определяет, когда выполняется так называемое преобразование "ToNumber". Когда это так, значение null и false преобразуются в 0.
& sect; 9.1 Преобразование типов и тестирование:
Таблица 14 - Конверсии чисел
Argument Type Result ------------- ------ Undefined Return NaN Null Return +0 Boolean Return 1 if argument is true. Return +0 if argument is false. Number Return argument (no conversion). String See grammar and note below.
Зная, когда применяется преобразование ToNumber, зависит от соответствующего оператора. Для реляционных операторов <
, <=
, >
и >=
см.:
& sect; 11.8.5 Алгоритм абстрактного реляционного сравнения:
Сравнение
x < y
, где x и y - значения, выражает true, false, или undefined (что указывает, что по крайней мере один операнд NaN). такие сравнение выполняется следующим образом:
Вызов ToPrimitive (x, номер подсказки).
Вызов ToPrimitive (y, номер подсказки).
Если тип (результат (1)) является строкой и типом (результат (2)) является строкой, перейдите к шагу 16. (Обратите внимание, что этот шаг отличается от шага 7 в алгоритме для оператор сложения + при использовании и вместо или.)
Вызов ToNumber (Результат (1)).
Вызов ToNumber (Результат (2)).
Оператор ==
отличается. Его преобразования типов описаны ниже. Обратите внимание, как null и false следуют различным правилам.
& sect; 11.9.3 Алгоритм сравнения абстрактного равенства
Сравнение x == y, где x и y - значения, выражает true или ложь. Такое сравнение выполняется следующим образом:
1. Если Тип (x) отличается от Type (y), перейдите к шагу 14.
...
14. Если x null, а y - undefined, верните true.
15. Если x undefined, а y null, верните true.
16. Если Type (x) - Number и Type (y) - String, верните результат сравнения x == ToNumber (y).
17. Если Type (x) - String и Type (y) - Number, верните результат сравнения ToNumber (x) == y.
18. Если Type (x) является логическим, верните результат сравнения ToNumber (x) == y.
19. Если Тип (y) является логическим, верните результат сравнения x == ToNumber (y).
20. Если Type (x) является либо String, либо Number и Type (y) - Object, верните результат сравнения x == ToPrimitive (y).
21. Если Type (x) - это Object и Type (y) - либо String, либо Number, верните результат сравнения ToPrimitive (x) == y.
22. Верните false.
Если вы внимательно прочитали, вы можете понять, почему false == 0
является true, но null == 0
является ложным.
Для false == 0
Тип (x) является булевым. Это означает, что применяется преобразование типа Step 18, а false преобразуется в число. ToNumber (false) равно 0, а 0 == 0
- true, поэтому сравнение выполняется успешно.
Для null == 0
Тип (x) - Null. Ни один из проверок типов не соответствует, поэтому сравнение проходит до шага 22, который возвращает значение false. Сравнение не выполняется.
null отличает 0 в виде числа: (+null)
равно 0. > и < приведем значение null к этому значению, поэтому по сравнению с числами оно действует как ноль. ==
не передает значение null в число, поэтому null == 0
является ложным.
Быстрый ответ можно найти в разнице между strict против "free" проверки равенства в JavaScript.
В большинстве случаев здесь хорошо справляются, но позвольте мне подчеркнуть, что урок сводится к следующему:
null == 0; // "loose" equality check with == gives true
null === 0; // strict equality check with === gives false
Это потому, что 0
и null
являются значениями ложности. То же самое касается и других членов клуба фальсификаций: undefined
, NaN
, ""
.
Они слабо равны ==
друг другу, но они строго равны только ===
.
null == 0; // true -- falsy loosely equals falsy
null === 0; // false -- but one falsy does not strictly equal another
0 === 0; // true -- one falsy strictly equals itself.
Также важно иметь в виду, что пустые объекты {}
и пустые массивы []
являются и правными.
Тогда реальная боль заключается в том, что нет строгих средств проверки того, является ли число числом и <= 0
одним оператором сравнения. <=
и >=
будут давать, как Джесси указывает true
по сравнению с чем-либо в нашем фальшивом клубе.
Это означает, что если вы хотите увидеть, является ли значение, которое может быть "ложным, отличным от 0", меньше или равно 0 (или больше или равно 0 и т.д.), вам нужно сделать довольно странную проверку...
function lessThanOrEqualsZero(value) {
return (value > 0 || value === 0); // literally "greater than or strictly equals"
}
Вы также можете быстро проверить утку...
function lessThanOrEqualsZero2(value) {
// Two paths: If number, less than or equals. Otherwise always false.
return parseInt(value, 10) ? value >= 0 : false;
}
Этот второй немного здесь - тернарный логический оператор оценивает NaN
, если он не будет числом, которое является ложным, и false
после возврата :
. Если это не NaN
- то есть, если это число - тогда вы можете сделать обычную проверку <=
, зная, что у вас нет неожиданного члена клуба фальсификации в value
.
<
или >
всегда является свободным сравнениемЭто означает решить эту проблему из OP...
null > -1
true
... вам нужно что-то вроде...
function strictGreaterThan(value) {
// If it not a number, *always return false*
return parseInt(value, 10) ? value > 0 : false;
}
Похоже, что JavaScript должен иметь "строго меньший, чем [или равный]" оператор, но не везет, строго говоря.
JavaScript - это весело, не так ли?