Talking About Undefined, Null, Not Defined, and Undeclared
In Javascript, there are several terms that sound superficially similar: undefined, null, not defined, and undeclared. If we are hearing these terms for the first time, we might feel that all of these terms are closely related, and perhaps they even describe the same concept. In reality, there are differences — quite significant ones — between each of these terms. Let’s examine them.
Undefined and Null
One unique thing in Javascript is the existence of the primitive value undefined alongside null. Both represent different things, where null, as in most programming languages, represents the absence of a value, while undefined represents the absence of a value being set.
They sound the same, right? For simplicity, the most visible difference is in who uses them, where undefined is used primarily by the Javascript engine while null is used intentionally by the programmer. This means that when we encounter undefined, it is most likely caused by an unintentional mistake like a syntax error.
The undefined value is used on variables that are declared without a value, missing function parameters, and unknown variables.
// deklarasi variabel tanpa isi
var a;
console.log(a); // undefined
var a = undefined; // pola seperti ini berarti no-op
// parameter fungsi yang kurang
function foo(bar, baz) {
console.log(bar, baz);
}
foo("hai"); // "hai" undefined
// variabel yang tidak dikenal
var obj = { a: 1 };
console.log(obj.b); // undefined
Meanwhile, null is available for developers to indicate the absence of a value in a variable. An example use case for null is as the default value of a function parameter.
function foo(bar, baz = null) {
// ...
if (baz !== null) { // ... }
}
Null and Undefined Coercion
Both null and undefined have their own data types. Therefore, both have their own coercion rules.
Both are included in false-y values in Javascript. This means that if we apply a Boolean operation to them, they will be treated as having the value false. For example, if we perform a cast-to-bool with the !! operator (I like to call it “bang, bang, you’re Boolean!”):
console.log(!!null); //false
console.log(!!undefined); //false
Up to this point, they sound very similar, don’t they? Especially if we compare the two values for equality:
null == undefined; // true
However, when we use the strict equality operator, the result will be different:
null === undefined; // false
This is because, as I mentioned earlier, both null and undefined are the exclusive values of their respective data types, so strictly speaking, they are two different things.
typeof undefined; // "undefined"
typeof null; // "object"
/*
** NOTE: tipe data null yang berupa objek adalah bug dalam Javascript,
** seharusnya tipe data null adalah null juga. Bug ini sengaja diabaikan
** untuk menjamin backward compatibility.
**/
Caveats for Checking Undefined
Checking for the undefined value can be done in three ways:
var x;
// cara pertama
x === undefined;
// cara kedua
typeof x === "undefined";
// cara ketiga
x === void 0;
The wrong way is to use a bang, such as if (!x) { //... }, because if x is not actually undefined but has a falsy value like "", "0", or even null, then x will pass the check.
What needs to be paid close attention to here is checking using the typeof operator. Suppose we check a variable foo. If foo has not been declared, then without using typeof, the check will throw Uncaught ReferenceError: foo is not defined. Also note that the return value of the typeof operator is a String.
typeof foo === "undefined"; // true
foo === undefined; // Uncaught ReferenceError: foo is not defined
Undefined or Not Defined?
An error with the message foo is not defined was mentioned earlier. Although they sound the same, undefined and not defined are two different things. When a variable is said to be not defined, it means the variable does not exist — it has not been declared at the time it is being referenced.
var foo;
foo === undefined; // true
bar === undefined; // Uncaught ReferenceError: bar is not defined
Personally, I feel that error would be better described as not declared.
Undeclared Variable
After undefined and not defined, there is also what is called an undeclared variable. Although it sounds similar, this phrase describes a completely different phenomenon.
A variable is said to be an undeclared variable when it is initialized without using a variable declaration keyword such as var, const, or let.
When we do that — say with a variable named foo — Javascript will try to find out whether foo has already been declared. The search starts from the scope where the foo expression resides, going up all the way to the global scope. If no declaration of foo is found up to the global scope, Javascript will create foo for you in the global scope. For more clarity, look at the example below:
function foo() {
var x = 10;
function bar() {
x = 15;
y = 2;
console.log(x); // 15
console.log(y); // 2
}
x += 5;
console.log(x); // 20
}
foo();
console.log(y); // 2
window.hasOwnProperty(y); // true
// padahal kita tidak pernah mendeklarasikan y pada global scope
There are two undeclared variables in the bar function, namely x and y. Searching upwards, the declaration of x is found in the scope of the foo function, so what happens is that x’s value is reassigned to 15. So the x thrown to console.log in the bar function is actually foo’s x. That is why when we do x += 5 below, the value of x becomes 20 instead of 15.
For the variable y, since no declaration is found when searching up to the global scope, Javascript creates a global variable y containing 2 for us. This event is often called a global variable leak.
Variable leakage all the way to the global scope can be a real threat to your code. In addition to unknowingly adding global variables, the existence of such undeclared variables can make the behavior of your code increasingly unpredictable. Avoid this by being more careful about declaring variables within each of your scopes.
Hopefully this article can provide clarity about undefined, null, not defined, and undeclared variable. If you have additions, objections, or questions, feel free to leave a comment in the section below.