Skip to main content

Command Palette

Search for a command to run...

Hoisting in JavaScript

Published
4 min readView as Markdown
Hoisting in JavaScript
B

I'm a web developer who aims to improve my own knowledge and skills while also helping others do the same.

Maybe you’ve heard of hoisting or maybe this is a new term in your learning journey. Either way, understanding how hoisting works will help you understand how your code works.

What the heck does hoisting even mean?

By definition, when something is “hoisted” it is the act of being lifted with mechanical devices like cranes or pulleys. So how does that have anything to do with coding? Truth be told, the term “hoisting” is confusing when looking at what truly happens when hoisting occurs.

In JavaScript, hoisting refers to the process of allocating space in memory for your functions and variables. This is confusing because developers often think that their functions and variables are lifted (or hoisted) to the top of the file, but that isn’t actually the case.

Let’s take a deeper look at what happens when our variables and functions are hoisted.

What is hoisting in JavaScript?

When an execution context is in the creation phase, it first reads over the code to find all functions and variables. As it finds functions and variables, it will allocate locations in memory for them to live. The biggest thing to consider is how var, let, and const variables are handled during hoisting.

Var

var variables are assigned the value undefined when they get hoisted. This is why you can access a var variable before it is defined in a JavaScript file. It’s not useful because you’ll always get undefined when accessing the variable before it’s assigned a proper value, but it doesn’t throw an error.

console.log(message); // undefined

var message = "Hello world!";
🚨
You should avoid using var in your code for this reason.

Let

let variables do not get assigned a value when they are hoisted, but they also do not need to have a value assigned when created in your code. If you try to access a let variable before it’s assigned a proper value, you’ll get a ReferenceError. A let variable cannot be accessed before it is defined in any circumstances.

console.log(message); // ReferenceError - Variable 'message' is used before it's declaration.

let message = "Hello world!";
💡
The time between hoisting and declaration is called the Temporal Dead Zone.

Since you don’t have to assign a value to a let variable, it will have the value undefined as long as it doesn’t have a value properly assigned. However that undefined value will only be returned if it isn’t assigned a proper value and you haven’t attempted to access the variable before it’s created.

let message;

console.log(message); // undefined

message = "Hello world!";

console.log(message); // Hello world!

Const

const variables must have a value assigned to them when they are declared. If you create a const variable without assigning a value to it, you will get a SyntaxError requiring you to assign a value. Once the value is assigned, it cannot be changed.

const message; // SyntaxError - 'const' declarations must be initialized
💡
A const variable initialized with a primitive type cannot be changed. The contents within an object or array can be changed later, but you cannot assign a new object or array to a const variable.

What about functions

Functions are hoisted in much the same way. When declaring a function using the function keyword, a location in memory is allocated for the function and it’s function body stored in that memory location. When the execution context goes through the execution phase, it will read the file line by line and execute the functions when they appear. Since the function body is stored in memory, you are able to run the function before it’s declared.

What about functions declared inside const variables, you say? These are much the same as regular const variables. They are assigned a location in memory, the function body is stored in memory, but it can not be called before it’s declared. It’s also worth noting that an arrow function stored in a const variable does not get it’s own this. Using this inside a const variable will reference it’s outer environment. This is different from a function declaration, which gets it’s own this.

Avoiding confusion

When thinking about hoisting, try to think less “these function and variable declarations are moved to the top of the file” and more “memory is allocated for these functions and variables”. Another point of confusion is that developers often think that let and const variables aren’t hoisted, which is incorrect. They are in fact hoisted, but are handled a little differently during hoisting.