Undefined vs Not Defined vs Null: JavaScript is Weird

Undefined vs Not Defined vs Null: JavaScript is Weird

JavaScript is a weird language when it comes to declarations & definitions. For a new developer, the differences between undefined, not defined & null can be confusing & it is understandable. So let's dive in, but before that you might want to consider reading my previous article on Execution Context & Call Stack so that you can have a clearer picture on how memory is allocated in JavaScript.

Undefined

Let's get started with undefined. It is a placeholder value which is assigned to a variable (only variables, not functions) when it is declared in a JavaScript program. Let's look at the below image.

image.png

Here I have a simple JavaScript program where I've put a breakpoint at line 2 & 5 for debugging. Now if I see the Call Stack (refer to this article for in-depth explanation), we have a Global object. Here all our variables & functions are defined. Now let's go step-by-step on breakpoints:

  1. Breakpoint 1: At this point (line 2), on expanding our Global object, we can see the variable hello. But right now our program execution is paused at line 2. So, you can see that our variable is undefined. This is because in the creation phase of our program, a placeholder value of undefined was assigned to the variable, i.e. memory for the variable hello was allocated but as the variable is yet to be initialized, hence, a placeholder value was assigned. In other languages, you might see an error in the console. It could be - The variable hello was never assigned a value! or something similar to this. But in JavaScript if you try to print this variable before it is initialized, it will print undefined in the console rather than throwing an exception. It will only throw an exception if you try to use the undefined variable in an expression. Let's say you're trying to apply a toUpperCase() function to this variable. It will throw an error of Uncaught TypeError: hello.toUpperCase is not a function.

  2. Breakpoint 2: At this point (line 5), we've already assigned a value to the variable in the previous line. So, the value of undefined in the memory is replaced by "Hello". It can be any value, even a number or an object. So now, if we try to print the variable, it will print "Hello" in the console as the value is initialized.

Not Defined

var hello;
console.log(hello);

hello = "Hello";
console.log(hello);

console.log(world);

Now let's say in the previous program, I add console.log(world); at line 7. This will result in an error - Uncaught ReferenceError: world is not defined. This is totally different than undefined. This results when a variable does not exist in the program at all, i.e., it is not even declared. JavaScript compiler is unable to find the reference to this variable in the memory. So if you expand the Global object, you won't find any variable named world.

image.png

Null

The value null represents the intentional absence of any object value. It is not an identifier like undefined. It is explicitly assigned to variables to show that the variable points to no object.

// Comparing null & undefined

var a = null; // assigned a value of null explicitly
var b; // assigned a placeholder value of undefined by default

console.log(null + 1); // 1
console.log(undefined + 1); // NaN

console.log(typeof null); // 'object'
console.log(typeof undefined); // 'undefined'

console.log(!!null); // false
console.log(!!undefined); // false

console.log(undefined == null); // true
console.log(undefined === null); // false

So this is how there 3 keywords differ in JavaScript. Remember, I said that undefined is only assigned to variables, not functions, this because when a function is allocated in the memory, the whole code is saved as it's value (refer to this article for in-depth explanation).

We can still assign undefined to a function using a variable. Let's have a look at the code below.

var a;

console.log(a, typeof a); // undefined, 'undefined'

a = () => {
  console.log("Hello");
}

console.log(a, typeof a); // [Function: a], 'function'

In the above example we're using the arrow syntax to define a function to a variable. That is why before the definition, it was undefined, but after the definition it became a function. But the important thing is, a was a variable before declaration.

Summary

  1. The keyword undefined is a placeholder value assigned by default to a variable during the Creation Phase. It is an identifier.

  2. Not Defined is basically an error which occurs when we try to access a variable which is not declared, i.e. does not exist in the memory.

  3. The keyword null is used to intentionally specify the absence of an object value. It is specified explicitly.