Explained the Secrets of JavaScript Hoisting: Avoid Common Pitfalls
If you've just started learning JavaScript, you may have encountered confusing issues like variables showing up as undefined
or mysterious ReferenceError
messages. This might be due to a concept called "hoisting." But what is hoisting, and how does it affect how your code runs?
In this guide, we’ll explain JavaScript hoisting in simple terms, so you can avoid common issues and write cleaner code. By the end, you'll understand what hoisting is and how it works in JavaScript.
What Exactly is Hoisting?
In simple terms, hoisting is JavaScript’s behaviour of moving variable and function declarations to the top of their scope before the code is executed. This means that variable and function declarations are processed before the actual code runs.
When your code is executed, the JavaScript engine first goes through a creation phase, during which it allocates memory for all variables and functions. However it treats functions and variables differently during this phase.
Function Hoisting: Full Definitions Are Moved
When you declare a function using the function
keyword, JavaScript stores the entire function in memory during the creation phase. As a result, you can call the function before its declaration in your code without any issues.
For example:
sum(2, 3); // Output: 5
function sum(x, y) {
console.log(x + y);
}
In this case, even though the sum()
function is called before it’s defined, the code works perfectly because JavaScript has already hoisted the entire function definition to the top of the scope.
Variable Hoisting: Different Rules for var
, let
, and const
Unlike functions, variables behave differently when hoisted. Let's explore the difference between var
, let
, and const
declarations.
1. var
Declarations
When you declare a variable using var
, the variable is hoisted with a default value of undefined
. This means that you can reference the variable before its declaration, but until the assignment happens, its value will be undefined
.
console.log(city); // Output: undefined
var city = "San Francisco";
console.log(city); // Output: "San Francisco"
In the code above, city
is hoisted to the top of the scope with a value of undefined
. That’s why the first console.log()
returns undefined
. After the variable is assigned a value, city
is updated, and the second console.log()
outputs "San Francisco."
2. let
and const
Declarations
With the introduction of ES6, JavaScript added let
and const
for variable declarations. Unlike var
, these variables are hoisted but not initialized. This means you cannot access them before their declaration, or you'll get a ReferenceError
.
console.log(name); // ReferenceError: Cannot access 'name' before initialization
const name = "Lydia Hallie";
This happens because let
and const
are in a state known as the Temporal Dead Zone (TDZ), which exists from the start of the block or function until the variable is declared. In this zone, accessing the variable results in a ReferenceError
.
Key Difference Between let
and const
Both let
and const
are hoisted, but the difference is that const
requires an initial value at the time of declaration, while let
does not. For example:
const name = "Lydia Hallie"; // Must be initialized
let info; // Can be declared without initialization
Hoisting in Action
Let’s combine both function and variable declarations in an example to see hoisting in action:
console.log(city); // Output: undefined
sum(2, 3); // Output: 5
function sum(x, y) {
console.log(x + y);
}
var city = "San Francisco";
console.log(city); // Output: "San Francisco"
Here, the sum
function is hoisted with its full definition, allowing it to be called even before the function is declared. However, the city
variable is hoisted with a value of undefined
, so the first console.log()
outputs undefined
. After the assignment, the second console.log()
correctly outputs "San Francisco."
Avoiding Common Hoisting Issues
Understanding hoisting can help you avoid common issues, especially when using var
. Here are some best practices:
Use
let
orconst
instead ofvar
to avoid accessing variables before their declaration.Always declare variables and functions at the top of your scope to make the flow of your code predictable and easy to read.
Key Takeaways
Hoisting moves variable and function declarations to the top of their scope during the creation phase.
Functions declared with
function
are hoisted with their entire definition, so you can call them before they are declared.Variables declared with
var
are hoisted with a default value ofundefined
, while variables declared withlet
andconst
are hoisted but remain uninitialized until their declaration.Temporal Dead Zone (TDZ) applies to
let
andconst
, which prevents you from using the variable before its declaration.
By understanding and applying these concepts, you can write more reliable and predictable JavaScript code. With practice, hoisting will become second nature!
Feel free to ask questions if anything is unclear—I'm happy to help! 😊
Subscribe to my newsletter
Read articles from Shubham Khan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Shubham Khan
Shubham Khan
Full-Stack Software Engineer with over 3 years of experience in building scalable web applications using React, Spring Boot, and RDBMS. Proven ability to enhance system performance, increase efficiency, and build secure authentication systems. Skilled in developing and deploying applications with cloud services like AWS and Docker, while driving team collaboration through Agile methodologies.