█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/JavaScript (Standalone Deep Dive)/Closures and Scope
45 minIntermediate

Closures and Scope

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.

Prerequisites:The JavaScript Engine

Lexical scope in one sentence

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.

Closures: the classic example

Read each line; understand what the returned function 'remembers'.

tsx
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3
// `count` lives as long as the returned function exists.
// Two counters = two independent closures over two separate `count`s.

The var-in-loop trap

The most-asked closure interview question.

tsx
// 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`.

The module pattern (closures as encapsulation)

Pre-ES6 way to hide private state. Still useful when you want truly private fields.

tsx
const counter = (() => {
let count = 0; // private
return {
increment() { count++; },
get() { return count; },
};
})();
counter.increment();
counter.get(); // 1
counter.count; // undefined, no external access

Common mistakes only experienced JS devs avoid

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.

Quick Check

What does this log? `for (var i = 0; i < 3; i++) setTimeout(() => console.log(i), 0);`

Pick the output.

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←The JavaScript Engine and Event Loop
Back to JavaScript (Standalone Deep Dive)
Prototypes and the Prototype Chain→