After this lesson, you will be able to: Master closures, lexical scope, the module pattern, and the closure pitfalls that catch every junior.
Closures are the most-tested JS interview topic. Understand them deeply or you'll be guessing.
A function 'closes over' the variables in scope where it was DEFINED, not where it was CALLED. The variables stay alive as long as the function does.
Read each line; understand what the returned function 'remembers'.
function makeCounter() {let count = 0;return function () {count++;return count;};}const counter = makeCounter();counter(); // 1counter(); // 2counter(); // 3// `count` lives as long as the returned function exists.// Two counters = two independent closures over two separate `count`s.
The most-asked closure interview question.
// Buggy with var (shared `i`)for (var i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100);}// Logs: 3 3 3 (all three callbacks see the SAME `i`, which is 3 after the loop)// Fixed with let (per-iteration binding)for (let i = 0; i < 3; i++) {setTimeout(() => console.log(i), 100);}// Logs: 0 1 2// Why `let` works: each iteration creates a NEW `i` in a fresh block scope.// The setTimeout callback closes over THAT specific `i`.
Pre-ES6 way to hide private state. Still useful when you want truly private fields.
const counter = (() => {let count = 0; // privatereturn {increment() { count++; },get() { return count; },};})();counter.increment();counter.get(); // 1counter.count; // undefined, no external access
var anywhere in modern code. const + let only. Closing over a loop variable expecting per-iteration capture (use let, not var). Treating a closure as 'free', long-lived closures hold references that prevent GC; memory leaks happen when listeners aren't removed. Forgetting that arrow functions close over `this` lexically; regular functions don't.
Pick the output.
Sign in and purchase access to unlock this lesson.