Hello Sunil
javascript-hoisting-feature-image

Hoisting in JavaScript : Beginners Guide

In JavaScript, hoisting allows you to use functions and variables before they are declared. In this post, we will learn what hoisting is and how it works.

Without wasting your time, Let’s begin with hoisting’s explanation.

Hoisting is JavaScript’s default behavior of moving declarations to the top of the function, if defined in a function, or the top of the global context, if outside a function.

What does it mean?

It means if you have declared a variable inside a function then its declaration part will move to the top.

But if your variable is not declared inside any function simply declared it in your program then it globally moves to the top.

Take a look at the code below and guess what happens when it runs:

Example – 1

var name= "Sunil Pradhan";
console.log(name);

//Output - Sunil Pradhan

As expected, it prints the value in the name variable to the console. Then what about the following code?

Example – 2

console.log(name);
var name= "Sunil Pradhan";

//Output - undefined

It might surprise you that this code outputs undefined and doesn’t fail or throw an error – even though name gets assigned after we console.log it!

Let us try removing the declaration and see what happens.

console.log(name);

//Output - ReferenceError: name is not defined

We got the error this time! What is happening?

In simple terms, we can say that in the second example, the code actually looks like the following to the JavaScript engine,

var name;
console.log(name);
name = "Sunil Pradhan";

It is putting the declaration of the variable at the top of the code and the name variable is assigned a value undefined and because we console it we get the same, this is an example of hoisting.

We can use hoisting with both Variables and Function so let’s take a deeper look at functions and variable hoisting to understand what this means and how it works.

As a reminder, in JavaScript we declare a variable with the var, let, and const.

For example:

var name;
let location;

We assign a variable a value using the assignment operator:

// Declaration
var name;
let location;

// Assignment
name = 'Sunil';
location = 'Bangalore';

In many cases, we can combine declaration and assignment into one step:

var name = 'Sunil';
let location = 'Bangalore';
const Education = 'B.Tech';

Variable hoisting acts differently depending on how the variable is declared. Let’s begin by understanding the behavior for var variables.

When the interpreter hoists a variable declared with var, it initializes its value to undefined. The first line of code below will output undefined:

console.log(name); // Output - undefined
var name = 'Sunil';

console.log(name); // Output - Sunil

As we defined earlier, hoisting comes from the interpreter splitting variable declaration and assignment.

We can achieve this same behavior manually by splitting the declaration and assignment into two steps:

var name;
console.log(name); // Output - undefined

name = 'Sunil';
console.log(name); // Output - Sunil

Remember that the first console.log(name) outputs undefined because name is hoisted and given a default value (not because the variable is never declared).

Using an undeclared variable will throw a ReferenceError instead:

// Uncaught ReferenceError: name is not defined
console.log(name); 

Using an undeclared variable before its assignment will also throw a ReferenceError because no declaration was hoisted:

// Uncaught ReferenceError: name is not defined
console.log(name); 

// Assigning a variable that's not declared is valid
name = 'Sunil';      

By now, you may be thinking, “Huh, it’s kind of weird that JavaScript lets us access variables before they are declared.”

This behavior is an unusual part of JavaScript and can lead to errors. Using a variable before its declaration is usually not desirable.

Thankfully the let and const variables, introduced in ECMAScript 2015, behave differently.

Variables declared with let and const are hoisted but not initialized with a default value. Accessing a let or const variable before it’s declared will result in a ReferenceError:

// Uncaught ReferenceError: 
// Cannot access 'name' before initialization
console.log(name); 

// Same behavior for variables declared with const
let name = 'Sunil';  

Notice that the interpreter still hoists name the error message tells us the variable is initialized somewhere.

The reason that we get a reference error when we try to access a let or const variable before its declaration is because of the temporal dead zone (TDZ).

The TDZ starts at the beginning of the variable’s enclosing scope and ends when it is declared.

Accessing the variable in this TDZ throws a ReferenceError.

Here’s an example with an explicit block that shows the start and end of foo‘s TDZ:

// Start of foo's TDZ
let bar = 'bar';
console.log(bar); // "bar"

// ReferenceError because we're in the TDZ
console.log(foo); 
let foo = 'foo';  // End of foo's TDZ

Function declarations are hoisted, too. Function hoisting allows us to call a function before it is defined.

For example, the following code runs successfully and outputs “Sunil”:

name(); // "Sunil"

function name() {
	console.log('Sunil');
}

Note that only function declarations are hoisted, not function expressions.

This should make sense: as we just learned, variable assignments aren’t hoisted.

If we try to call the variable that the function expression was assigned to, we will get a TypeError or ReferenceError, depending on the variable’s scope:

// Uncaught TypeError: foo is not a function
foo(); 
var foo = function () { }

// Uncaught ReferenceError: 
// Cannot access 'bar' before initialization
bar(); 
let bar = function () { }

// Uncaught ReferenceError: 
// Cannot access 'baz' before initialization
baz(); 
const baz = function () { }

This differs from calling a function that is never declared, which throws a different ReferenceError:

foo(); // Uncaught ReferenceError: foo is not defined

Because of the confusion that var hoisting can create, it’s best to avoid using variables before they are declared. If you are writing code in a greenfield project, you should use let and const to enforce this.

If you are working in an older codebase or have to use var for another reason, MDN recommends that you write var declarations as close to the top of their scope as possible. This will make the scope of your variables more clear.

You can also consider using the no-use-before-define ESLint rule which will ensure you don’t use a variable before its declaration.

Function hoisting is useful because we can hide function implementation farther down in the file and let the reader focus on what the code is doing.

In other words, we can open up a file and see what the code does without first understanding how it’s implemented.

Take the following contrived example:

resetScore();
drawGameBoard();
populateGameBoard();
startGame();

function resetScore() {
	console.log("Resetting score");
}

function drawGameBoard() {
	console.log("Drawing board");
}

function populateGameBoard() {
	console.log("Populating board");
}

function startGame() {
	console.log("Starting game");
}

We immediately have an idea of what this code does without having to read all the function declarations.

Hoisting in JavaScript is a mechanism in which the variables and function declarations are moved to the top of their scope before the execution of the code.

The function expressions and arrow functions cannot be hoisted. On the other hand, all the variables in JavaScript are hoisted.

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Similar articles you may like

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.

Add comment

Stay Updated

Want to be notified when our article is published? Enter your email address below to be the first to know.

Sunil Pradhan

Hi there 👋 I am a front-end developer passionate about cutting-edge, semantic, pixel-perfect design. Writing helps me to understand things better.