← Back to JavaScript
11

Scope, hoisting and the TDZ: why your variable exists or fails on each line

Learn lexical scope, hoisting and the temporal dead zone so you can avoid ReferenceError, fix variable shadowing and write more predictable functions.

📘 Theory

A conceptual map of scope, hoisting and the TDZ

Three connected ideas explain why a variable works in one place and breaks in another.

Scope defines where you can access a variable. Hoisting explains which declarations are processed before line-by-line execution begins. The temporal dead zone marks the stretch where `let` and `const` already exist but still cannot be used.

If you understand this trio, your errors stop feeling random and become fully traceable.

1

Global scope

Visible from the whole file or module.

  • Useful for shared configuration
  • Dangerous when overused because it couples too much code
2

Function scope

Variables live only inside the function.

  • Encapsulates logic
  • Reduces side effects
3

Block scope

With `let` and `const`, the variable lives inside `{}`.

  • `if`, `for` and `while` create blocks
  • It prevents accidental variable leaks
4

TDZ

The temporal dead zone of `let` and `const`.

  • The binding exists before initialization
  • Reading it too early causes `ReferenceError`

Lexical scope: the block decides

The place where you declare a variable determines who can see it.

1

JavaScript uses lexical scope. It does not matter where a function is called from. What matters is where it was defined.

2

In real code, that idea becomes crucial when you work with event handlers and nested functions.

Real hoisting without myths

Not everything is hoisted in the same way. One thing gets declared, another gets initialized.

Function declarations are available before their line appears. With `var`, the declaration is hoisted but the initial value is `undefined` until assignment. With `let` and `const`, there is hoisting too, but no access before initialization because of the TDZ.

That is why it helps to declare variables near the top of their block and helper functions before their first use when possible.

The TDZ: a useful error, not your enemy

The temporal dead zone protects you from using variables too early.

The TDZ begins when the block starts and ends on the line where you initialize the `let` or `const` binding.

That early `ReferenceError` prevents silent bugs that used to slip through much more easily with `var`.

  • If you hit the TDZ, inspect the declaration and initialization order.
  • Do not mix definition and use inside long blocks without structure.
  • Prefer smaller functions to reduce mental context.

Shadowing and naming: avoid accidental confusion

You can redeclare inside an inner block, but do it carefully.

1

Shadowing happens when an inner variable hides another one from an outer scope by using the same name. It is not always wrong, but it often creates confusion.

2

In team code, semantically different names such as `basePrice` and `priceWithTax` are usually much clearer than reusing `price` everywhere.

🧭 Key visuals

Scope and variable visibility

It reinforces how variables are resolved depending on the execution context.

Diagram of global scope, block scope and function scope

🧪 Learn by doing

Example Guided example: scope in an access validation Observe which variables live inside the block and which ones stay accessible outside it.
Example Guided example: hoisting in a function versus `var` Compare the behavior and see why not everything gets hoisted in the same way.
Example Interactive demo: scope and TDZ viewer Choose a case and inspect the result of each scope pattern in both the preview and the console.

🏁 Challenges

Challenge Challenge 1: fix a TDZ error by changing the declaration order Reorder the code so a `let` binding is initialized before it gets used.
Challenge Challenge 2: avoid confusing shadowing Refactor the names so the inner and outer variables do not collide semantically.

What is this?

I'm Cristian Eslava and I sometimes build websites so both you and I can learn and experiment. culTest

I made this in February 2026 to make learning easier for my students. The idea is to learn web development by practicing and to keep expanding the project with new topics, tests and challenges.

It draws inspiration from MDN, W3Schools, CodePen, Manz and many other web development references. I wanted to combine useful theory, runnable examples, challenges and the testing system I had already built for culTest. culTest

If you liked it, if you didn't, or if you want to get in touch, write to me at cristianeslava@gmail.com