JavaScript hoisting is a fundamental concept that can sometimes confuse even experienced developers. Understanding it thoroughly helps avoid common pitfalls and write cleaner code. This post breaks down hoisting in variables, functions, and classes, explains the Temporal Dead Zone (TDZ), and highlights best practices to manage them effectively.
What is Hoisting?
Hoisting refers to JavaScript’s behaviour where declarations (not initializations) of variables, functions, and classes are moved—"hoisted"—to the top of their current scope before code execution. This means you can sometimes use variables or functions before you declare them in the code.
Hoisting in Variables: var vs let vs const
var declarations are hoisted and
initialized with
undefined. So accessing them before the declaration gives
undefined, not an error.
let and const declarations are hoisted but not initialised. They stay in the Temporal Dead Zone (TDZ) from the start of the block until the line where they are declared.
Temporal Dead Zone (TDZ) Explained
The TDZ is the time window between entering a scope and the actual initialisation of a let or const variable. During this time, the variable exists but can't be accessed.
Why reference errors occur:
JavaScript knows about
x but forbids using it until its definition to avoid unpredictable behaviours.
Function Hoisting: Declarations vs Expressions
Function declarations are fully hoisted—including their bodies. You can call the function even before its declaration.
Function expressions (including arrow functions) assigned to var/let/const are only hoisted as variable declarations, but not initialised as functions. Calling them before initialisation throws an error.
Class Hoisting
Class declarations behave like let/const. The class is hoisted but not initialised — accessing before declaration triggers ReferenceError.
Execution Context: Hoisting + TDZ + Errors
When JavaScript runs code, it creates an Execution Context for each scope, including a variable environment. During the compile phase, declarations are hoisted, but initialisations happen during execution.
Accessing uninitialized
let, const, or classes causes errors due to TDZ. Understanding this helps debug unexpected
ReferenceErrors and
TypeErrors.
var vs let vs const in Practice
Initialized on hoisting
Yes (undefined)
No
No
Block scoped
No (function)
Yes
Yes
Avoid Hoisting & TDZ Issues: Best Practices
- Always declare variables at the top of scopes to avoid confusion.
- Prefer const and let over var for clearer scoping and TDZ safety.
- Avoid calling functions before declaration when using function expressions.
- Use function declarations if you need hoisting, but understand scope rules.
- Write code to minimise dependency on hoisting behaviour — it improves readability and reduces bugs.
- Initialise variables at declaration whenever possible.
Summary Example
Understanding hoisting, Temporal Dead Zone(TDZ), and differences between declarations in JavaScript is key to mastering the language and writing robust, bug-free code.