Temporal Dead Zone
This lesson explains Temporal Dead Zone with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.
ES6+ Temporal Dead Zone Overview
The Temporal Dead Zone, often called the TDZ, is the period between
entering a scope and reaching the line where a
let or const variable is declared. During
this time, the variable exists but cannot be accessed.
If you try to use a let or const variable
before its declaration, JavaScript throws a
ReferenceError. This behavior helps prevent confusing
bugs that were common with hoisted var variables.
| Feature | Description |
| Concept Name | Temporal Dead Zone (TDZ) |
| Applies To | let and const |
| Error Type | ReferenceError |
| Starts | When scope begins |
| Ends | At variable declaration line |
| Main Benefit | Prevents use-before-declaration bugs |
Basic Temporal Dead Zone Example
console.log(count);
let count = 10;
// ReferenceError:
// Cannot access 'count' before initialization
let count = 10;
console.log(count);
In the first example, count is inside the TDZ when
console.log(count) runs, so JavaScript throws an error.
After the declaration line, the variable can be used normally.
How the Temporal Dead Zone Works
When JavaScript enters a block or function scope, bindings for
let and const are created immediately.
However, they remain uninitialized until the declaration statement
is executed.
| Step | Description | Result |
| Enter Scope | Block or function starts executing. | Binding is created. |
| TDZ Begins | Variable exists but is uninitialized. | Access throws ReferenceError. |
| Reach Declaration | let or const line runs. | Variable is initialized. |
| TDZ Ends | Variable becomes usable. | Normal reads and writes work. |
| Leave Scope | Block or function finishes. | Binding is destroyed. |
TDZ vs var Hoisting
console.log(total);
var total = 100;
console.log(total);
console.log(score);
let score = 100;
console.log(score);
A hoisted var variable returns
undefined before assignment, which can hide bugs. A
let variable in the TDZ throws a clear
ReferenceError instead.
Temporal Dead Zone in Block Scope
{
console.log(message);
let message = "Hello";
console.log(message);
}
Block scope creates its own TDZ for let and
const variables. Even inside a small
{ } block, accessing the variable before
declaration is not allowed.
Temporal Dead Zone with const
console.log(API_URL);
const API_URL =
"https://api.example.com";
const MAX_USERS = 50;
console.log(MAX_USERS);
const follows the same TDZ rules as
let. The difference is that after initialization,
const cannot be reassigned.
typeof and the Temporal Dead Zone
console.log(typeof missingVar);
var missingVar = 5;
console.log(typeof value);
let value = 5;
With an undeclared or hoisted var,
typeof may return "undefined". With a
let or const variable in the TDZ,
typeof also throws a ReferenceError.
TDZ Inside Functions
function createUser() {
console.log(username);
let username = "Alex";
return username;
}
createUser();
function showTotal() {
let total = 0;
total = total + 10;
console.log(total);
}
showTotal();
Each function call creates a new scope and its own TDZ for local
let and const bindings. Declare variables
before using them inside functions.
TDZ in Loops
for (let i = 0; i < 3; i += 1) {
console.log(i);
}
let index = 0;
while (index < 3) {
console.log(index);
index += 1;
}
A for loop with let creates a fresh
binding on each iteration. TDZ rules still apply if you try to use
the loop variable before the declaration part of the loop runs.
TDZ with Function Parameters
function greet(name = username) {
let username = "Guest";
return `Hello, ${name}`;
}
greet();
function buildMessage(
prefix = "Info",
message = `${prefix}: Ready`
) {
return message;
}
console.log(buildMessage());
Default parameter expressions are evaluated in the function's
scope. If a default tries to access a later
let or const declaration, the variable
may still be in the TDZ and cause a ReferenceError.
TDZ with Classes
const app = new App();
class App {
constructor() {
this.name = "Dashboard";
}
}
class User {
constructor(name) {
this.name = name;
}
}
const user = new User("Alex");
console.log(user.name);
Class declarations are also subject to TDZ behavior. You cannot
use a class before its declaration line, similar to
let and const.
Why the Temporal Dead Zone Exists
- It prevents confusing
undefined values from hoisted variables. - It makes use-before-declaration bugs easier to detect.
- It encourages clearer variable declaration order.
- It aligns behavior more closely with block scope rules.
- It improves code safety in modern JavaScript applications.
TDZ Behavior Comparison
| Declaration Type | Before Declaration | After Declaration |
var | undefined | Assigned value |
let | ReferenceError | Assigned value |
const | ReferenceError | Assigned value, no reassignment |
class | ReferenceError | Class is usable |
Why Understanding TDZ Matters
- Debugging
ReferenceError messages in modern code. - Writing safer block-scoped variables with
let and const. - Avoiding bugs in loops, functions, and default parameters.
- Understanding why
var behavior feels different. - Reading transpiled or linted code more confidently.
- Designing clearer initialization flows in applications.
Temporal Dead Zone Best Practices
- Declare
let and const before first use. - Prefer declaring variables at the top of a block when practical.
- Use
const by default and let when reassignment is needed. - Avoid relying on hoisting behavior from older
var patterns. - Be careful with default parameters referencing later declarations.
- Enable lint rules such as
no-use-before-define. - Initialize variables close to where their values are known.
Common Temporal Dead Zone Mistakes
- Assuming
let behaves like hoisted var. - Using a variable before its declaration line in the same scope.
- Expecting
typeof to safely hide TDZ errors. - Creating circular references in default parameter expressions.
- Using a class before its declaration.
- Shadowing outer variables and accessing the inner one too early.
- Debugging TDZ errors without checking declaration order.
Fix a TDZ Error
// Problem
function displayPrice() {
console.log(price);
let price = 49.99;
}
// Solution
function displayPrice() {
let price = 49.99;
console.log(price);
}
displayPrice();
The simplest fix is to move the declaration above the first use.
This keeps the variable out of the TDZ when it is accessed.
Key Takeaways
- The Temporal Dead Zone is the period before a
let or const declaration runs. - Accessing variables in the TDZ throws a
ReferenceError. var hoisting returns undefined, but let and const do not. - TDZ applies in blocks, functions, loops, parameters, and classes.
- Declaring variables before use prevents TDZ bugs and makes code easier to maintain.
Pro Tip
When you see "Cannot access before initialization", check the
declaration order first. Moving the let or
const line above the first use usually fixes the
problem immediately.