Hoisting in JavaScript: Understanding var, let, and const


I used to believe that hoisting in JavaScript only applied to variables declared with the var
keyword. However, I recently discovered that variables declared with let
and const
are also hoisted, though they behave differently. In this article, I’ll explain what hoisting is, how it works with var
, let
, and const
, and why these differences matter for writing reliable code.
What is Hoisting?
Hoisting is a JavaScript mechanism where variable and function declarations are moved to the top of their containing scope during the compilation phase, before the code executes. However, only the declarations are hoisted — not the initializations or assignments. This behavior affects how and when variables can be accessed in your code.
Hoisting with var
Variables declared with var
are hoisted to the top of their scope—either the global scope or the function scope. During the creation phase of the execution context, these variables are allocated memory and automatically initialized to undefined
. This explains why you can access a var
variable before its declaration without triggering an error, though its value will be undefined
until assigned.
Example:
console.log(x); // Output: undefined
var x = 10;
console.log(x); // Output: 10
What’s Happening?
The JavaScript engine creates the Global Execution Context (GEC).
In the creation phase, the declaration
var x
is hoisted, andx
is initialized toundefined
.When
console.log(x)
runs,x
exists but has the valueundefined
.Later,
x = 10
assigns the value, so the secondconsole.log(x)
outputs10
.
Key Point: Variables declared with var
are hoisted and initialized to undefined
, making them accessible (though undefined) before their declaration.
Hoisting with let
and const
Variables declared with let
and const
are also hoisted, but unlike var
, they are not initialized until the code reaches their declaration. This uninitialized period—from the start of their block scope to their declaration—is called the Temporal Dead Zone (TDZ). Attempting to access these variables before their declaration results in a ReferenceError
.
Example:
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 20;
console.log(y); // Output: 20
What’s Happening?
The declaration
let y
is hoisted to the top of its scope.However,
y
remains in the Temporal Dead Zone until the linelet y = 20
executes.Accessing
y
before this line throws aReferenceError
because it’s hoisted but not initialized.
Another Example:
console.log(x); // ReferenceError: x is not defined
let y = 10;
Here,
x
is undeclared, so JavaScript throwsReferenceError: x is not defined
.In contrast, accessing
y
before its declaration results inReferenceError: Cannot access 'y' before initialization
, showing thaty
is hoisted but inaccessible due to the TDZ.
Key Point: Variables declared with let
and const
are hoisted but remain in the Temporal Dead Zone until their declaration, preventing access before initialization.
Conclusion
All variables — whether declared with
var
,let
, orconst
—are hoisted in JavaScript, meaning their declarations are moved to the top of their scope.var
variables are initialized withundefined
, allowing access before declaration (though with an undefined value).let
andconst
variables are hoisted but remain in the Temporal Dead Zone until their declaration, causing aReferenceError
if accessed early.
Understanding hoisting and its differences across var
, let
, and const
is crucial for avoiding unexpected errors and writing cleaner, more predictable JavaScript code.
Acknowledgments: Thanks to WebDev Cohort 1 by ChaiCode for deepening my understanding of this topic.
#chaiaurcode #chaicode
Subscribe to my newsletter
Read articles from Pranav Bagal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
