Scope & var/let/const (the TDZ)
Scope answers one question: where can I see this variable? Getting it right is the difference between a clean program and one full of names that leak, clash, or mysteriously hold the wrong value.
Learn Scope & var/let/const (the TDZ) in our free JavaScript course — a beginner-friendly interactive lesson with runnable examples, a practice exercise and…
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
We'll compare var , let , and const head to head, walk the scope chain, revisit the Temporal Dead Zone, and finally explain that famous loop bug.
What You'll Learn in This Lesson
📚 Prerequisites: Read Hoisting first — scope and hoisting are two sides of the same coin. Comfort with functions helps too.
💡 Running Code Locally: While this online editor runs real JavaScript, some advanced examples may have limitations. For the best experience:
- Download Node.js to run JavaScript on your computer
- Use your browser's Developer Console (Press F12) to test code snippets
- Create a .html file with <script> tags and open it in your browser
🏢 Real-World Analogy: Scope is like rooms in an office building:
- • A note pinned inside a room (block) is visible only in that room
- • Someone inside the room can also read notes in the hallway (outer scope)
- • Someone in the hallway can't read notes locked inside the room
- • var ignores room walls (function scope); let / const respect them (block scope)
1️⃣ Global, Function & Block Scope
A variable's scope is the region of code where its name is valid. There are three levels: global (the whole program), function (inside one function), and block (inside any { } — an if , a loop, a bare block). let and const are block-scoped; var only respects functions.
2️⃣ var Leaks Out of Blocks
Here's the headline difference. Declare a var inside an if or loop and it escapes the block — it's visible in the whole function. A let in the same place stays politely contained. This leak is a classic source of subtle bugs.
3️⃣ The Scope Chain
When you reference a name, JavaScript searches the current scope, then the one enclosing it, and so on outward until it hits global. The first match wins — a phenomenon called shadowing when an inner name hides an outer one of the same name.
🎯 Your Turn #1 — Keep It Contained
Change the declaration so secret stays inside the block and the outer log throws.
4️⃣ The Famous Loop Bug — var vs let
This is the interview classic. With var , the loop shares a single i , so every deferred callback reads its final value. With let , each iteration gets a fresh binding, so callbacks capture the value they had at the time. Same loop, one keyword apart.
5️⃣ const Protects the Binding, Not the Value
A common surprise: you can mutate a const object. const only forbids pointing the name at something new — it doesn't freeze the contents. To lock the contents too, reach for Object.freeze() .
🎯 Your Turn #2 — Fix the Loop
Swap one keyword so the callbacks capture 0, 1, 2 instead of all threes.
🧩 Reorder Challenge
These lines are scrambled. Reorder them so the inner function can read outer and it logs hi .
Why: inner reads message via the scope chain at call time, so message (a const ) must be initialised before inner() runs.
🧠 Quick Recall
Predict the output before revealing the answer.
1 — var is function-scoped, so it leaks out of the if block.
2 — const blocks reassigning the binding, but the object's contents can still change.
in out — the inner x shadows the outer one inside f ; outside, the global x is unchanged.
Common Errors & Fixes
- 1️⃣ Leaky var in loops and ifs
- 2️⃣ Accidental globals (no keyword)
- 3️⃣ Expecting const to freeze contents
- 4️⃣ Reading a let before its line
Quick Reference — var / let / const
Keyword
Scope
Reassign?
Before declaration
var
Function
✅ Yes
undefined
let
Block
TDZ → ReferenceError
const
❌ No
Rule of thumb: default to const , use let when you must reassign, avoid var .
Frequently Asked Questions
Lesson Complete — Scope & var/let/const!
- ✅ Scope is global, function, or block — let / const respect blocks, var doesn't
- ✅ The scope chain searches inner → outer; inner names shadow outer ones
- ✅ let gives a fresh per-iteration binding — the loop bug fix
- ✅ const locks the binding, not the contents; Object.freeze() does both
Up next: Map & Set — purpose-built collections beyond plain objects and arrays. 🗺️
Practice quiz
Which keyword is function-scoped rather than block-scoped?
- let
- const
- var
- block
Answer: var. var is function-scoped, so it ignores inner { } blocks; let and const are block-scoped.
What does this log? function demo() { if (true) { var leaky = 'I escaped!'; } console.log(leaky); } demo();
- I escaped!
- ReferenceError
- undefined
- ''
Answer: I escaped!. var leaks out of the if block to the whole function, so leaky is still 'I escaped!' after the block.