Skip to content

Hoisting

October 29, 2022

JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, classes to the top of their scope. Before execution of the code.

Types of hoisting

We can categorieze hoisting into three following behaviors.

1) Value hoisting

Use a variable's value in its scope before the line it is declared. For function declarations.

javascript
foo(); // Hello there
function foo() {
console.log("Hello there");
}

2) Declaration hoisting

Reference a variable in its scope before the line it is declared, without throwing a ReferenceError, but the value is always undefined. For var declaration.

javascript
console.log(foo); // undefined
var foo = 2;
javascript
console.log(foo); // undefined
foo(); // Uncaught TypeError: foo is not a function
var foo = function () {
console.log("---");
};
javascript
console.log(foo); // undefined
foo(); // Uncaught TypeError: foo is not a function
var foo = () => {
console.log("---");
};

All variables get hoisted.

  • When the var variables are hoisted they are initialized with the value undefined.
  • When the let and const variables are hoisted they are not initialized with any value. (That is the reason the temporal dead zone exists.)

3) Class hoisting

A class declaration is uninitialized when hoisted. (TDZ like let and const). Meaning while JavaScript can find the reference for a class we declared, it cannot use the class before it is defined in the code.

javascript
let student = new Student(); // ReferenceError: Student is not defined (because of TDZ)
student.name = "Kagan";
class Student {
constructor(name) {
this.name = name;
}
}

Temporal Dead Zone (TDZ)

The declaration of the variable causes behavior changes in its scope before the line in which it is declared. For let, const, and class declarations.

javascript
console.log(foobar); // ReferenceError: foobar is not defined
let foobar = 2;

TDZ with line shadowing:

javascript
let foo = 1;
{
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
let foo = 2;
}
javascript
foo(); // ReferenceError: foo is not defined
console.log(foo); // ReferenceError: foo is not defined
let foo = function () {
console.log("---");
};

TDZ for automatically global variables:

javascript
console.log(num); // ReferenceError: num is not defined
num = 6; // Initialization

TDZ for classes:

javascript
let student = new Student(); // ReferenceError: Student is not defined
student.name = "Kagan";
student.age = 25;
class Student {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

Why does JavaScript hoist variables and functions?

There is not a specific justification or definition for hoisting variables and functions. Infact there is no such thing as hoisting.

Hoisting is merely a side effect of the compilation phase that occurs and the fact that Javascript is lexically scoped. It wasn't even reference in the Ecmascript spec before the es2015 release.

The JS code interpretation performed in two passes.

  1. Code compilation step, the interpreter processes variable and function declarations. It puts all variable and function declarations in memory as it figures out the lexical scopes that exists in the program.

  2. Code execution step, the interpreter processes function expressions and undeclared variables.

"It puts all variable and function declarations in memory" Is the part where the word hoisting happens.

At the end of the day, hoisting is one of those fancy words we all use, often because its easier to use rather than explain and discuss the compilation process that javascript goes through.

Profile picture

I have a passion for all things web.