⚡ Lesson 14 of 30
Scope & Closures
Understand variable scope, the scope chain, lexical environments, and the power of closures.
Block Scope with let/const
let and const are block-scoped — they only exist inside the {} they are declared in:
{
let x = 10;
const y = 20;
console.log(x, y); // 10 20
}
// console.log(x); // ReferenceError!
Function Scope
Variables declared with var (or function parameters) are scoped to the enclosing function:
function greet() {
var message = "Hello!";
console.log(message); // "Hello!"
}
greet();
// console.log(message); // ReferenceError!
The Scope Chain
Inner functions can access variables from outer functions — this forms the scope chain:
function outer() {
const x = 10;
function inner() {
const y = 20;
console.log(x + y); // 30 — x from outer scope
}
inner();
}
outer();
Closures
A closure is a function that remembers the variables from the scope where it was created, even after that scope has finished executing:
function makeCounter(start = 0) {
let count = start; // "closed over"
return {
increment() { count++; },
decrement() { count--; },
value() { return count; },
};
}
const counter = makeCounter(10);
counter.increment();
counter.increment();
console.log(counter.value()); // 12
Practical Closure: Memoization
Closures enable powerful patterns like memoization (caching expensive results):
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (key in cache) return cache[key];
return (cache[key] = fn(...args));
};
}
const factorial = memoize(n => n <= 1 ? 1 : n * factorial(n - 1));
console.log(factorial(6)); // 720