Why is null in JavaScript bigger than -1, less than 1, but not equal (==) to 0? What is it exactly then?
JavascriptJavascript Problem Overview
From the Google Chrome console:
var x = null;
undefined
x > 0
false
x < 0
false
x > -1
true
x < 1
true
x == 1
false
x === 1
false
Javascript Solutions
Solution 1 - Javascript
When you compare null for equality to 0, the result is false. If you force null
to be interpreted in a numeric context then it is treated like 0 and the result becomes true.
You can force it to be numeric by putting +
in front, or by using numeric operators like <
, <=
, >
, and >=
. Notice how null >= 0
and null <= 0
are both true.
> null == 0
false
> +null == 0
true
> null >= 0
true
> null <= 0
true
The ECMAScript Language Specification defines when a so-called "ToNumber" conversion is performed. When it is, null and false are both converted to 0.
> ### §9.1 Type Conversion and Testing: > > Table 14 — To Number Conversions > >
> 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. >
Knowing when the ToNumber conversion is applied depends on the operator in question. For the relational operators <
, <=
, >
, and >=
see:
> ### §11.8.5 The Abstract Relational Comparison Algorithm:
>
> The comparison x < y
, where x and y are values, produces true, false,
> or undefined (which indicates that at least one operand is NaN). Such
> a comparison is performed as follows:
>
> 1. Call ToPrimitive(x, hint Number).
>
> 2. Call ToPrimitive(y, hint Number).
>
> 3. If Type(Result(1)) is String and Type(Result(2)) is String, go to step 16. (Note that this step differs from step 7 in the algorithm for
> the addition operator + in using and instead of or.)
>
> 4. Call ToNumber(Result(1)).
>
> 5. Call ToNumber(Result(2)).
The ==
operator is different. Its type conversions are described below. Notice how null and false follow different rules.
> ### §11.9.3 The Abstract Equality Comparison Algorithm > > The comparison x == y, where x and y are values, produces true or > false. Such a comparison is performed as follows: > > 1. If Type(x) is different from Type(y), go to step 14. > > ... > > 14. If x is null and y is undefined, return true. > > 15. If x is undefined and y is null, return true. > > 16. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y). > > 17. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y. > > 18. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y. > > 19. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y). > > 20. If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y). > > 21. If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y. > > 22. Return false.
If you read carefully you can see why false == 0
is true but null == 0
is false.
-
For
false == 0
, Type(x) is Boolean. This means Step 18's type conversion is applied, and false is converted to a number. ToNumber(false) is 0, and0 == 0
is true, so the comparison succeeds. -
For
null == 0
, Type(x) is Null. None of the type checks match so the comparison falls through to Step 22, which returns false. The comparison fails.
Solution 2 - Javascript
null casts to 0 as a number: (+null)
is 0. > and < cast null to this value, so when compared to numbers it acts as zero. ==
doesn't cast null to a number, so null == 0
is false.