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

Почему `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?

4b9b3361

Ответ 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 !