I want to know what the difference is between null
and undefined
in JavaScript.
The best way to understand the difference is to first clear your mind of the inner workings of JavaScript and just understand the differences in meaning between:
let supervisor = "None"
// I have a supervisor named "None"
let supervisor = null
// I do NOT have a supervisor. It is a FACT that I do not.
let supervisor = undefined
// I may or may not have a supervisor. I either don't know
// if I do or not, or I am choosing not to tell you. It is
// irrelevant or none of your business.
There is a difference in meaning between these three cases, and JavaScript distinguishes the latter two cases with two different values, null
and undefined
. You are free to use those values explicitly to convey those meanings.
So what are some of the JavaScript-specific issues that arise due to this philosophical basis?
A declared variable without an initializer gets the value undefined
because you never said anything about the what the intended value was.
let supervisor;
assert(supervisor === undefined);
A property of an object that has never been set evaluates to undefined
because no one ever said anything about that property.
const dog = { name: 'Sparky', age: 2 };
assert(dog.breed === undefined);
null
and undefined
are "similar" to each other because Brendan Eich said so. But they are emphatically not equal to each other.
assert(null == undefined);
assert(null !== undefined);
null
and undefined
thankfully have different types. null
belongs to the type Null
and undefined
to the type Undefined
. This is in the spec, but you would never know this because of the typeof
weirdness which I will not repeat here.
A function reaching the end of its body without an explicit return statement returns undefined
since you don't know anything about what it returned.
By the way, there are other forms of "nothingness" in JavaScript (it's good to have studied Philosophy....)
NaN
ReferenceError
let
or const
defined local variable in its temporal dead zone and receiving a ReferenceError
Empty cells in sparse arrays. Yes these are not even undefined
although they compare ===
to undefined.
$ node
> const a = [1, undefined, 2]
> const b = [1, , 2]
> a
[ 1, undefined, 2 ]
> b
[ 1, <1 empty item>, 2 ]
Both special values imply an empty state.
The main difference is that undefined represents the value of a variable that wasn’t yet initialized, while null represents an intentional absence of an object.
The variable number is defined, however, is not assigned with an initial value:
let number;
number; // => undefined
number variable is undefined, which clearly indicates an uninitialized variable
The same uninitialized concept happens when a non-existing object property is accessed:
const obj = { firstName: 'Dmitri' };
obj.lastName; // => undefined
Because lastName property does not exist in obj, JavaScript correctly evaluates obj.lastName to undefined.
In other cases, you know that a variable expects to hold an object or a function to return an object. But for some reason, you can’t instantiate the object. In such a case null is a meaningful indicator of a missing object.
For example, clone() is a function that clones a plain JavaScript object. The function is expected to return an object:
function clone(obj) {
if (typeof obj === 'object' && obj !== null) {
return Object.assign({}, obj);
}
return null;
}
clone({name: 'John'}); // => {name: 'John'}
clone(15); // => null
clone(null); // => null
However, clone() might be invoked with a non-object argument: 15 or null (or generally a primitive value, null or undefined). In such case, the function cannot create a clone, so it returns null - the indicator of a missing object.
typeof operator makes the distinction between the two values:
typeof undefined; // => 'undefined'
typeof null; // => 'object'
The strict quality operator === correctly differentiates undefined from null:
let nothing = undefined;
let missingObject = null;
nothing === missingObject; // => false
null: absence of value for a variable; undefined: absence of variable itself;
..where variable is a symbolic name associated with a value.
JS could be kind enough to implicitly init newly declared variables with null, but it does not.
null and undefined are two distinct object types which have the following in common:
==
and !=
operators.The similarities however end here. For once, there is a fundamental difference in the way how keywords null and undefined are implemented. This is not obvious, but consider the following example:
var undefined = "foo";
WScript.Echo(undefined); // This will print: foo
undefined, NaN and Infinity are just names of preinitialized "superglobal" variables - they are initialized at run-time and can be overridden by normal global or local variable with the same names.
Now, let's try the same thing with null:
var null = "foo"; // This will cause a compile-time error
WScript.Echo(null);
Oops! null, true and false are reserved keywords - compiler won't let you use them as variable or property names
Another difference is that undefined is a primitive type, while null is an object type (indicating the absense of an object reference). Consider the following:
WScript.Echo(typeof false); // Will print: boolean
WScript.Echo(typeof 0); // Will print: number
WScript.Echo(typeof ""); // Will print: string
WScript.Echo(typeof {}); // Will print: object
WScript.Echo(typeof undefined); // Will print: undefined
WScript.Echo(typeof null); // (!!!) Will print: object
Also, there is an important difference in the way null and undefined are treated in numeric context:
var a; // declared but uninitialized variables hold the value undefined
WScript.Echo(a === undefined); // Prints: -1
var b = null; // the value null must be explicitly assigned
WScript.Echo(b === null); // Prints: -1
WScript.Echo(a == b); // Prints: -1 (as expected)
WScript.Echo(a >= b); // Prints: 0 (WTF!?)
WScript.Echo(a >= a); // Prints: 0 (!!!???)
WScript.Echo(isNaN(a)); // Prints: -1 (a evaluates to NaN!)
WScript.Echo(1*a); // Prints: -1.#IND (in Echo output this means NaN)
WScript.Echo(b >= b); // Prints: -1 (as expected)
WScript.Echo(isNaN(b)); // Prints: 0 (b evaluates to a valid number)
WScript.Echo(1*b); // Prints: 0 (b evaluates to 0)
WScript.Echo(a >= 0 && a <= 0); // Prints: 0 (as expected)
WScript.Echo(a == 0); // Prints: 0 (as expected)
WScript.Echo(b >= 0 && b <= 0); // Prints: -1 (as expected)
WScript.Echo(b == 0); // Prints: 0 (!!!)
null becomes 0 when used in arithmetic expressions or numeric comparisons - similarly to false, it is basically just a special kind of "zero". undefined, on the other hand, is a true "nothing" and becomes NaN ("not a number") when you try to use it in numeric context.
Note that null and undefined receive a special treatment from ==
and !=
operators, but you can test true numeric equality of a and b with the expression (a >= b && a <= b)
.
You might consider undefined to represent a system-level, unexpected, or error-like absence of value and null to represent program-level, normal, or expected absence of value.
via JavaScript:The Definitive Guide
Undefined means a variable has been declared but has no value:
var var1;
alert(var1); //undefined
alert(typeof var1); //undefined
Null is an assignment:
var var2= null;
alert(var2); //null
alert(typeof var2); //object