Почему `null >= 0 && null <= 0`, но не` null == 0`?
Мне пришлось написать процедуру, которая увеличивает значение переменной на 1, если ее тип равен number
и присваивает 0 переменной, если нет, где исходная переменная первоначально null
или undefined
.
Первая реализация была v >= 0 ? v += 1 : v = 0
, потому что я думал, что что-то не число сделает арифметическое выражение ложным, но это было неправильно, так как null >= 0
оценивается как true. Затем я узнал, что 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
оценивается как false. Это делает кажущееся тавтологическое выражение (v >= 0 && v <= 0) === (v == 0)
ложным.
Почему null
как 0, хотя на самом деле это не 0?
Ответы
Ответ 1
Кажется, что ваш реальный вопрос:
Почему:
null >= 0; // true
Но:
null == 0; // false
Что действительно происходит, так это то, что Оператор большего или равного (>=
) выполняет принуждение типа (ToPrimitive
), с типом подсказки Number
, на самом деле все реляционные операторы имеют такое поведение.
null
особым образом обрабатывается оператором Equals (==
). Короче говоря, он только приближается к undefined
:
null == null; // true
null == undefined; // true
Значение, такое как false
, ''
, '0'
и []
, подвержено циклическому типу, все из которых принуждают к нулю.
Вы можете увидеть внутренние детали этого процесса в Алгоритм сравнения абстрактного равенства и Алгоритм сравнения реляционных сравнений.
В резюме:
-
Реляционное сравнение: если оба значения не являются строками String, на обоих вызывается ToNumber
. Это то же самое, что и добавление +
спереди, которое для нулевых когерентностей равно 0
.
-
Сравнение равенств: только вызовы ToNumber
в строках, числах и булерах.
Ответ 2
Я хотел бы расширить вопрос, чтобы еще больше улучшить видимость проблемы:
null >= 0; //true
null <= 0; //true
null == 0; //false
null > 0; //false
null < 0; //false
Это просто не имеет смысла. Как человеческие языки, эти вещи нужно изучать наизусть.
Ответ 3
JavaScript имеет как строгие, так и типовые преобразования
null >= 0;
истинно
но
(null==0)||(null>0)
false
null <= 0;
истинно, но (null==0)||(null<0)
является ложным
"" >= 0
также верно
Для реляционных абстрактных сравнений (< =, > =) операнды сначала преобразуются в примитивы, а затем к тому же типу перед сравнением.
typeof null returns "object"
Когда тип - объект javascript пытается стягивать объект (например, null)
выполняются следующие шаги (ECMAScript 2015):
- Если
PreferredType
не было передано, пусть hint
будет "по умолчанию".
- Иначе, если
PreferredType
есть hint
String, пусть hint
будет "string".
- Else
PreferredType
- hint
Число, пусть hint
будет "числом".
- Пусть
exoticToPrim
be GetMethod(input, @@toPrimitive)
.
-
ReturnIfAbrupt(exoticToPrim)
.
- Если
exoticToPrim
не undefined, тогда
а) Пусть результат будет Call(exoticToPrim, input, «hint»)
.
б) ReturnIfAbrupt(result)
.
c) Если Type(result)
не объект, верните результат.
d) Выбросить исключение TypeError.
- Если
hint
является "значением по умолчанию", пусть hint
будет "числом".
- Возврат
OrdinaryToPrimitive(input,hint)
.
Допустимыми значениями для подсказок являются "по умолчанию", "число" и "строка". Объекты Date уникальны среди встроенных объектов ECMAScript в том смысле, что они рассматривают значение по умолчанию как эквивалентное "string".
Все остальные встроенные объекты ECMAScript относятся к стандарту по умолчанию как к числу "число" . (ECMAScript 20.3.4.45)
Итак, я думаю, что null
преобразуется в 0.
Ответ 4
У меня была такая же проблема!!.
В настоящее время мое единственное решение - отделить.
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 !