Why `null = 0 && null = 0` but not `null == 0`?
Your real question seem to be:
Why:
null >= 0; // true
But:
null == 0; // false
What really happens is that the Greater-than-or-equal Operator (>=
), performs type coercion (ToPrimitive
), with a hint type of Number
, actually all the relational operators have this behavior.
null
is treated in a special way by the Equals Operator (==
). In a brief, it only coerces to undefined
:
null == null; // true
null == undefined; // true
Value such as false
, ''
, '0'
, and []
are subject to numeric type coercion, all of them coerce to zero.
You can see the inner details of this process in the The Abstract Equality Comparison Algorithm and The Abstract Relational Comparison Algorithm.
In Summary:
Relational Comparison: if both values are not type String,
ToNumber
is called on both. This is the same as adding a+
in front, which for null coerces to0
.Equality Comparison: only calls
ToNumber
on Strings, Numbers, and Booleans.
Why is null in JavaScript bigger than -1, less than 1, but not equal (==) to 0? What is it exactly then?
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:
Call ToPrimitive(x, hint Number).
Call ToPrimitive(y, hint Number).
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.)Call ToNumber(Result(1)).
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.
Javascript comparison question (null = 0)
The relational operators (>=
and <=
), perform type coercion (ToPrimitive
), with a hint type of Number
, all the relational operators present have this behavior.
You can see the inner details of this process in the The Abstract Relational Comparison Algorithm.
On the other hand, the Equals operator (==
), if an operand is null
it only returns true
if the other is either null
or undefined
, no numeric type coercion is made.
null == undefined; // true
null == null; // true
Check the inner details of this process in the The Abstract Relational Comparison Algorithm.
Recommended articles:
typeof
,==
and===
- Notes on ECMAScript Equality Operators
How do I check for null values in JavaScript?
JavaScript is very flexible with regards to checking for "null" values. I'm guessing you're actually looking for empty strings, in which case this simpler code will work:
if(!pass || !cpass || !email || !cemail || !user){
Which will check for empty strings (""
), null
, undefined
, false
and the numbers 0
and NaN
.
Please note that if you are specifically checking for numbers, it is a common mistake to miss 0
with this method, and num !== 0
is preferred (or num !== -1
or ~num
(hacky code that also checks against -1
)) for functions that return -1
, e.g. indexOf
).
Handle null = 0 in Typescript
You can employ a type guard that will assure the compiler that you're not handling a null
but a number. Moreover, it will make the code more correct, since with value: any
this means you might get a boolean or a string passed in:
public print(value: any): void {
if (typeof value === "number") {
//value is definitely a number and not null
if (value >= 0) {
console.log('Greater than zero')
}
}
}
Playground Link
Now the code specifically verifies that you do get a number and then checks if it's more than or equal to zero. This means that a null
or a non-number value would not be processed.
The type guard condition can be combined with the other for brevity:
public print(value: any): void {
if (typeof value === "number" && value >= 0) {
console.log('Greater than zero')
}
}
Playground Link
Or extracted on its own to just reduce the nesting:
public print(value: any): void {
if (typeof value !== "number")
return;
//value is definitely a number and not null
if (value >= 0) {
console.log('Greater than zero')
}
}
Playground Link
What is the difference between NULL, '\0' and 0?
Note: This answer applies to the C language, not C++.
Null Pointers
The integer constant literal 0
has different meanings depending upon the context in which it's used. In all cases, it is still an integer constant with the value 0
, it is just described in different ways.
If a pointer is being compared to the constant literal 0
, then this is a check to see if the pointer is a null pointer. This 0
is then referred to as a null pointer constant. The C standard defines that 0
cast to the type void *
is both a null pointer and a null pointer constant.
Additionally, to help readability, the macro NULL
is provided in the header file stddef.h
. Depending upon your compiler it might be possible to #undef NULL
and redefine it to something wacky.
Therefore, here are some valid ways to check for a null pointer:
if (pointer == NULL)
NULL
is defined to compare equal to a null pointer. It is implementation defined what the actual definition of NULL
is, as long as it is a valid null pointer constant.
if (pointer == 0)
0
is another representation of the null pointer constant.
if (!pointer)
This if
statement implicitly checks "is not 0", so we reverse that to mean "is 0".
The following are INVALID ways to check for a null pointer:
int mynull = 0;
<some code>
if (pointer == mynull)
To the compiler this is not a check for a null pointer, but an equality check on two variables. This might work if mynull never changes in the code and the compiler optimizations constant fold the 0 into the if statement, but this is not guaranteed and the compiler has to produce at least one diagnostic message (warning or error) according to the C Standard.
Note that the value of a null pointer in the C language does not matter on the underlying architecture. If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.
As such, even on this funny architecture, the following ways are still valid ways to check for a null pointer:
if (!pointer)
if (pointer == NULL)
if (pointer == 0)
The following are INVALID ways to check for a null pointer:
#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
as these are seen by a compiler as normal comparisons.
Null Characters
'\0'
is defined to be a null character - that is a character with all bits set to zero. '\0'
is (like all character literals) an integer constant, in this case with the value zero. So '\0'
is completely equivalent to an unadorned 0
integer constant - the only difference is in the intent that it conveys to a human reader ("I'm using this as a null character.").
'\0'
has nothing to do with pointers. However, you may see something similar to this code:
if (!*char_pointer)
checks if the char pointer is pointing at a null character.
if (*char_pointer)
checks if the char pointer is pointing at a non-null character.
Don't get these confused with null pointers. Just because the bit representation is the same, and this allows for some convenient cross over cases, they are not really the same thing.
References
See Question 5.3 of the comp.lang.c FAQ for more.
See this pdf for the C standard. Check out sections 6.3.2.3 Pointers, paragraph 3.
Related Topics
How to Toggle an Element's Class in Pure JavaScript
How to Copy Static Files to Build Directory with Webpack
Scrolling an Iframe with JavaScript
How to Limit Google Autocomplete Results to City and Country Only
JavaScript Event Handler with Parameters
How to Access Local Scope Dynamically in JavaScript
How to Duplicate Object Properties in Another Object
Differencebetween Substr and Substring
How to Create Dynamic Variable Names Inside a Loop
How Many Bytes in a JavaScript String
Getting Unexpected Token Export
How to Use Z-Index in Svg Elements
iPad Web App: Detect Virtual Keyboard Using JavaScript in Safari
Sorting in JavaScript: Should Every Compare Function Have a "Return 0" Statement
Find and Remove Objects in an Array Based on a Key Value in JavaScript
Why Does Array.Prototype.Push Return the New Length Instead of Something More Useful