Why This Matters
You've been creating variables inside functions and loops — but have you noticed that a variable created inside a function can't be used outside it? That's scope at work. Scope is the set of rules that determines where in your code a variable is visible and accessible.
Misunderstanding scope is one of the most common sources of bugs. A variable that "disappears," a function that reads the wrong value, or a name collision between two parts of your code — these are all scope problems. Master scope and you'll understand why your variables behave the way they do.
Define Terms
Visual Model
The full process at a glance. Click Start tour to walk through each step.
Nested scopes: each inner scope can access variables from all outer scopes, but not vice versa.
Code Example
// GLOBAL SCOPE
let count = 0; // accessible everywhere
function increment() {
// FUNCTION SCOPE
let step = 1; // only accessible inside increment()
count += step; // can access global "count"
if (count > 5) {
// BLOCK SCOPE
let message = "Limit reached!"; // only in this block
console.log(message);
}
// console.log(message); // ERROR: message is not defined
}
increment();
increment();
console.log(count); // 2
// console.log(step); // ERROR: step is not defined
// CLOSURE: a function that remembers its outer scope
function makeCounter() {
let n = 0;
return function() {
n++;
return n;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3Interactive Experiment
Try these exercises:
- Create a variable inside a function and try to access it outside — what error do you get?
- Create two functions that each have a variable named
xwith different values. Do they interfere with each other? - Build a closure: a function that returns another function. Call the returned function multiple times — does it remember state?
- In Python, try accessing a variable created inside an
ifblock from outside it. Compare with JavaScript.
Quick Quiz
Coding Challenge
Write a function called `createCounter` that takes a starting number and returns an object with two methods: `increment()` which adds 1 and returns the new count, and `getCount()` which returns the current count. Use closures to keep the count private.
Real-World Usage
Scope is everywhere in production code:
- Module systems: Each file/module creates its own scope.
import/exportcontrol what's visible. - React hooks:
useStateuses closures to persist state across re-renders. - Event handlers: Closures capture variables from the enclosing scope when the handler was defined.
- Private state: JavaScript classes use closures (or
#privatefields) to hide internal data. - Middleware: Express middleware functions close over configuration passed at setup time.