Почему `null> = 0 && null <= 0`, а не` null == 0`? - PullRequest
133 голосов
/ 26 мая 2010

Мне пришлось написать подпрограмму, которая увеличивает значение переменной на 1, если ее тип равен number, и присваивает 0 переменной, если нет, где переменная изначально равна null или undefined.

Первая реализация была v >= 0 ? v += 1 : v = 0, потому что я думал, что что-либо, кроме числа, сделает арифметическое выражение ложным, но это было неправильно, поскольку null >= 0 оценивается как истинное. Затем я узнал, что null ведет себя как 0, и все следующие выражения оцениваются как true.

  • null >= 0 && null <= 0
  • !(null < 0 || null > 0)
  • null + 1 === 1
  • 1 / null === Infinity
  • Math.pow(42, null) === 1

Конечно, null не равно 0. null == 0 оценивается как ложное. Это делает, казалось бы, тавтологическое выражение (v >= 0 && v <= 0) === (v == 0) ложным.

Почему null равно 0, хотя на самом деле это не 0?

Ответы [ 4 ]

199 голосов
/ 26 мая 2010

Ваш реальный вопрос:

Почему:

null >= 0; // true

Но:

null == 0; // false

Что действительно происходит, так это то, что оператор «Больше или равно» (>=) выполняет приведение типов (ToPrimitive) с подсказкой типа Number, фактически все реляционные операторы имеют такое поведение.

null обрабатывается особым образом оператором Equals (==). Короче говоря, это только принуждает до undefined:

null == null; // true
null == undefined; // true

Значения, такие как false, '', '0' и [], подвергаются принуждению числового типа, все они приводятся к нулю.

Вы можете увидеть внутренние детали этого процесса в Алгоритме сравнения абстрактного равенства и Алгоритм абстрактного сравнения отношений .

В итоге:

  • Реляционное сравнение: если оба значения не являются типом String, ToNumber вызывается для обоих. Это то же самое, что добавить + впереди, что для нулевых принуждений к 0.

  • Сравнение равенства: только вызовы ToNumber для строк, чисел и логических значений.

12 голосов
/ 14 марта 2017

Я хотел бы расширить вопрос для дальнейшего улучшения видимости проблемы:

null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0;  //false
null < 0;  //false

Это просто не имеет смысла. Подобно человеческим языкам, эти вещи нужно изучать наизусть.

4 голосов
/ 09 августа 2017

JavaScript имеет строгие сравнения и сравнения типов

null >= 0; верно но (null==0)||(null>0) ложно

null <= 0; верно, но (null==0)||(null<0) неверно

"" >= 0 также верно

Для реляционных абстрактных сравнений (<=,> =) операнды сначала преобразуются в примитивы, затем в тот же тип перед сравнением.

typeof null returns "object"

Когда тип является объектом, javascript пытается структурировать объект (т. Е. Null) предпринимаются следующие шаги ( ECMAScript 2015 ):

  1. Если PreferredType не было передано, пусть hint будет "по умолчанию".
  2. Иначе, если PreferredType равно hint String, пусть hint будет "строкой".
  3. Иначе PreferredType - это hint Число, пусть hint будет "числом".
  4. Пусть exoticToPrim будет GetMethod(input, @@toPrimitive).
  5. ReturnIfAbrupt(exoticToPrim).
  6. Если exoticToPrim не является неопределенным, то
    а) Пусть результат будет Call(exoticToPrim, input, «hint»).
    б) ReturnIfAbrupt(result).
    c) Если Type(result) не является объектом, вернуть результат.
    г) Бросить исключение TypeError.
  7. Если hint «по умолчанию», пусть hint будет «числом».
  8. Возврат OrdinaryToPrimitive(input,hint).

Допустимые значения для подсказки: «по умолчанию», «число» и «строка». Объекты Date уникальны среди встроенных объектов ECMAScript в том смысле, что они рассматривают «default» как эквивалент «string». Все другие встроенные объекты ECMAScript обрабатывают «default» как эквивалент «number» . ( ECMAScript 20.3.4.45 )

Так что я думаю null конвертируется в 0.

1 голос
/ 14 мая 2017

У меня была такая же проблема !! В настоящее время мое единственное решение состоит в том, чтобы отделить.

var a = null;
var b = undefined;

if (a===0||a>0){ } //return false  !work!
if (b===0||b>0){ } //return false  !work!

//but 
if (a>=0){ } //return true !
...