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

Почему в JavaScript ноль больше, чем -1, меньше 1, но не равно (==) 0? Что именно тогда?

Из консоли Google Chrome:

var x = null;
undefined
x > 0
false
x < 0
false
x > -1
true
x < 1
true
x == 1
false
x === 1
false
4b9b3361

Ответ 1

Когда вы сравниваете значение 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. Сравнение не выполняется.

Ответ 2

null отличает 0 в виде числа: (+null) равно 0. > и < приведем значение null к этому значению, поэтому по сравнению с числами оно действует как ноль. == не передает значение null в число, поэтому null == 0 является ложным.

Ответ 3

Это равенство, строго говоря,

Быстрый ответ можно найти в разнице между 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 - это весело, не так ли?