Many JavaScript developers, both junior and senior, often find themselves confused about the null
and undefined
types. This misunderstanding of the two types does not come without a cost: errors and bugs.
Before diving deeper, let’s first cover the basics:
undefined
undefined
is returned if a variable was only declared but not assigned a value.
For example:
var ab
This will log undefined
:
log(ab)
undefined variables are variables that are with no values. Let’s say the environment is represented like this:
environmentVariable = {
}
JS engine would interpret the VariableDeclaration var ab
as:
environmentVariable = {
ab: undefined
}
So when it is accessed the undefined
will be returned. Now, when the ab
is assigned a value:
ab = 90
The undefined
will be changed to the value 90
:
environmentVariable = {
ab: 90
}
When we declared ab
it was set in the environment variable table as undefined
, meaning the value is on the way, now when we ab to value 90
, the undefined
was changed to 90
. Now if we log ab it will no longer be undefined
:
// ...
log(ab)
// 90
undefined
can also occur if an object’s property doesn’t exist
let myDetails = {
age: 27
}log(myDetails.name)
// undefined
or a function has a missing parameter:
function getMyDetails(a) {
l(a)
}getMyDetails()
// undefined
undefined
is a primitive data type in JS:
Boolean
Undefined
Number
String
Symbolvar ab
typeof ab
// undefined
You can check for the type using typeof
keyword:
if(typeof ab == 'undefined') {
// ...
}
undefined
can be set explicitly:
var ab = undefined
l(ab)
// undefinedab = 90
l(ab)
// 90
null
null
is a data type in JS that declares no value or non-existent value. null can be thought of as an intentional absence of any object value.
var ab = null
l(ab)
// null
Let’s look at their similarities.
Both are falsy values
null
and undefined
always resolves to a falsy value. They are among the falsy values in JS:
If they are in the condition of an if-else
statement, the else statement will always be executed:
if (null) {
l('yes')
} else {
l('no')
}
The above will log “no”.
if (undefined) {
l('yes')
} else {
l('no')
}
will also log “no”.
Both are primitive values
In JS we have Complex and Primitive data types, null and undefined are among the primitive data types:
Primitive data types are resolved by value-of-reference.
null
and undefined
means no-value but they resolve to diff. values:
l(typeof null)
// objectl(typeof undefined)
// undefined
You were expecting typeof null
would return “null”? Right? This is a bug in JS for nearly two decades, but the thing is that it cannot be fixed. This is because thousands of websites depend on this buggy behavior, fixing it will make them break.
null
is an assigned value, it must be explicitly assigned by the programmer. IF not assigned, the variable becomes undefined
:
var ab = null
var a // undefined
unlike undefined which can be explicitly assigned or unassigned:
var ab = undefined
var bc l(ab)
// undefinedl(bc)
// undefined
null
We saw that undefined
resolves to “undefined” but null
resolves to “object”.
We can easily test for undefined
:
var abif(typeof ab == "undefined") {
// ...
}
For null
, we can’t do this:
var ab = nullif(typeof ab == "null") {
// ...
}
typeof null
returns “object” and we can be tempted to rewrite the above like this:
var ab = nullif(typeof ab == "object") {
// ...
}
Many Complex data types return objects, the type can be checked via typeof
:
let obj = {}
let arr = []
class D {}
const d = new D()l(typeof obj)
l(typeof arr)
l(typeof d)// object
// object
// object
So it would fail because an Array or Object might be the value of ab.
Now how do we correctly test for null, as null is a falsy value we will combine its check with the typeof check.
var ab = nullif(!ab && typeof ab == "object") {
// ...
}
Let’s see what happens when strict and loose equality are performed on both types. But before that — a quick review of the loose equality specification:
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
Look at 2 and 3
2 says if the LHS is null and the RHS is undefined, true is returned. This is why if we do this:
log(null == undefined)
it logs true
log(null == undefined)
// true
and says if the LHS is undefined and the RHS is null, it should also return true
log(undefined == null)
// true
This means that null and undefined are loosely equal, yes, it is understandable because they all represent an absence of no value, like in a key-value pair, the key is present but the value is not present/ is absent.
Let’s see about Strict Equality:
The comparison x === y, where x and y are values, produces true or false. Such a comparison is performed as follows:
looking at the above, strict equality returns false if the RHS and LHS types are different
Now, in the case of
null === undefined
This will be false because the types will be object
and undefined
, see they are different so it will return false.
log(null === undefined)
So,
null !== undefined
will be true. Why? It is because null => object
is not the same type as undefined => undefined
.
Understand this, The operator !==
is asking whether the LHS is not strictly equal to RHS? So, in our case, yes(true) the LHS(null => object) is not strictly equal to the RHS(undefined => undefined).
null != undefined
This is asking if the LHS is not equal to the RHS. This is no, they are equal because Abstract Equality says to return true(that they are equal) if the LHS is either null
or undefined
and the RHS is either null
or undefined
.
null
and undefined
as a function argumentWe should be careful when declaring default argument value like this:
function defFunc(name = "nnamdi") {
return name
}
This function just returns a name passed to it, see the argument name
has a default value nnamdi
, the argument will take nnamdi
as value when the function is called with no parameters:
log(defFunc())
// nnamdi
It can be said like this, when the argument name is undefined it assumes the nnamdi
value. So if we pass an undefined value to defFunc
name will be nnamdi
:
var ab
log(defFunc(ab))
// nnamdi
Now, what happens if we pass in null to the function? Do you think it will log nnamdi because null means the absence of a value or will it log null because null is a value? Let’s see:
log(defFunc(null))
// null
Wow!! it logged null. It should be because null is an object. I would say an empty object, yet still representing the absence of a value(s).
If you try to check for null argument, remember don;t do this:
function defFunc(name = "nnamdi") {
if(typeof name == "null")
return "nnamdi"
return name
}
do this:
function defFunc(name = "nnamdi") {
if(!name && typeof name == "object")
return "nnamdi"
return name
}
or you can delegate the null check to a function:
function isNull(val) {
return !val && typeof val == "object"
}
you can use the isNull
function anywhere in your program:
function defFunc(name = "nnamdi") {
if(isNull(name))
return "nnamdi"
return name
}
I think we are clear on the disparities and similarities between null
and undefined
. So when next you see that error, you will know what to do.
Thanks !!!
#javascript