You will face hoisting early when you write JavaScript. It affects how your code runs, and it may confuse you if you do not expect it. In this guide, you will understand hoisting in detail, from the basics to how it works under the hood with examples.
Table of Content
Understand Hoisting in JavaScript
Hoisting means JavaScript moves variable and function declarations to the top of their scope during the compile phase.
This happens before the code runs. JavaScript does not move the values, only the declarations. That is why you may use a variable before you define it—sometimes.
Many new developers get stuck when a variable looks like it should be undefined but has a value. Or when they call a function before they define it, and it works.
These cases come from hoisting. If you understand it, you avoid bugs and write clearer code.
var
declarations get hoisted to the top of the function or global scope. The variable becomes known at the top but stays undefined until the assignment line.
let
and const
also get hoisted, but they do not behave the same. They sit in a “temporal dead zone” between the top of the scope and the line where they appear. You cannot use them before the declaration line.
console.log(x); // undefined
var x = 5;
console.log(y); // ReferenceError
let y = 10;
Output:
undefined
/index.js:4
console.log(y); // ReferenceError
^
ReferenceError: Cannot access 'y' before initialization
at Object.<anonymous> (/index.js:4:13)
In the example above, x
is hoisted and becomes undefined at first. y
is also hoisted, but it stays unreachable until the line where you define it.
So, how does JavaScript hoisting affect scope?
Hoisting works inside each scope. If you declare a variable inside a function with var
, the hoisting only applies to that function.
function test() {
console.log(a);
var a = 3;
}
test(); // undefined
In this case, the a
variable gets hoisted to the top of the function. Global variables follow the same rule—var
goes to the top of the global scope.
let
and const
still follow block scope, so if you define them inside an if
block, they only live in that block. Hoisting still applies, but you cannot touch them early.
How JavaScript Engines Handle Hoisting
When the JavaScript engine starts, it scans the code and sets up memory for variables and functions. This happens before it runs any line of code.
The engine creates two phases:
- Compilation phase – It allocates memory for variables and functions. It hoists declarations to the top.
- Execution phase – It runs your code from top to bottom.
In the compile phase, var
gets a memory slot with the value undefined
. let
and const
get memory slots but stay uninitialized until the declaration runs.
The Difference Between Hoisting var, let, and const with Examples in JavaScript
Here is what changes when you use different keywords:
var
gets hoisted and initialized withundefined
.let
gets hoisted but not initialized. Access before the declaration throws an error.const
works likelet
, but you must assign a value when you declare it.
console.log(a); // undefined
var a = 1;
console.log(b); // ReferenceError
let b = 2;
console.log(c); // ReferenceError
const c = 3;
Output:
undefined
/index.js:4
console.log(b); // ReferenceError
^
ReferenceError: Cannot access 'b' before initialization
at Object.<anonymous> (/index.js:4:13)
var
lets you write less strict code, but it leads to bugs. let
and const
make hoisting rules clearer.
How to Debug Hoisting in JavaScript
To avoid hoisting problems, follow these steps:
- Declare variables at the top of their scope.
- Always use
let
orconst
. - Use strict mode with
'use strict';
to catch mistakes early. - Do not rely on using functions or variables before you define them.
You can also use breakpoints in the browser’s developer tools. Step through the code to watch how the engine handles each line.
Hoisting in ES6
Before ES6, var
and function declarations worked with hoisting only. ES6 added let
, const
, and block scope. These newer keywords changed how hoisting works.
Now, hoisting still happens, but the behavior of let
and const
adds a safeguard. The “temporal dead zone” stops you from using variables before they get declared.
Also, arrow functions and function expressions do not hoist like function declarations.
sayHi(); // Works
function sayHi() {
console.log("Hi");
}
sayBye(); // TypeError
const sayBye = function () {
console.log("Bye");
};
Output:
Hi
/index.js:6
sayBye(); // TypeError
^
ReferenceError: Cannot access 'sayBye' before initialization
at Object.<anonymous> (/index.js:6:1)
Function declarations hoist the full function. Function expressions do not. That is why the second case fails.
Let’s move on to the following section to see more examples of hoisting in JavaScript.
Examples of Hoisting in JavaScript
Here are a few more clear examples:
function demo() {
console.log(x); // undefined
var x = 10;
}
demo();
The x
variable moves to the top inside the demo
function. You see undefined
.
{
console.log(b); // ReferenceError
let b = 5;
}
Output:
/index.js:2
console.log(b); // ReferenceError
^
ReferenceError: Cannot access 'b' before initialization
at Object.<anonymous> (/index.js:2:15)
Here, b
sits in the temporal dead zone. You cannot use it early.
foo(); // "hello"
function foo() {
console.log("hello");
}
Function foo
works fine. The full function hoists.
bar(); // TypeError
var bar = function () {
console.log("world");
};
Output:
/index.js:1
bar(); // TypeError
^
TypeError: bar is not a function
at Object.<anonymous> (/index.js:1:1)
The variable bar
hoists but only gets undefined
. You call it before the assignment.
Wrapping Up
Hoisting can confuse you if you do not know how it works. Once you understand how JavaScript handles declarations before it runs code, the behavior starts to make sense.
var
, let
, and const
all get hoisted, but they act differently. Functions may hoist too, but only if you use function declarations.
You do not need to avoid hoisting. You just need to write code that works with it. Keep your declarations at the top.
Use let
and const
to make your scope and timing clear. If you get an error or unexpected value, check how hoisting might have caused it.
Thank you for reading. Click here to see more JavaScript tutorials.