Glossary / Closures

Closures

A closure is a function together with access to the lexical environment in which it was created. Closures let functions preserve access to local bindings after the outer function returns. They are fundamental to callbacks, event handlers, factories, modules, memoization, and functional composition. JavaScript creates closures automatically; developers choose what state those functions retain and how long references stay alive.

Captured bindings, not frozen snapshots

function makeCounter(start) {
  let value = start;
  return {
    next() { return ++value; },
    current() { return value; },
  };
}
const counter = makeCounter(10);
counter.next();    // 11
counter.current(); // 11

Both returned methods close over the same value binding. They observe its latest state, not a copied number from creation time. If a closure captures a mutable object, mutations to that object are visible too. Loop closures using var historically shared one binding; let creates a per-iteration binding.

Lifetime and memory

A closure can keep referenced values reachable. A global event listener that closes over a large component tree may prevent that tree from being collected after its UI disappears. Remove listeners, cancel timers, unsubscribe, or abort requests when the owner is disposed. Garbage collectors can optimize unused bindings, but code should not rely on such optimizations to manage resource lifetime.

Closures can provide encapsulation, but they are not a security boundary: returned methods can expose state, and captured objects can be mutated through aliases. Use explicit objects/classes when lifecycle and ownership deserve visible structure.

Interview questions

  1. What does a closure capture? Access to lexical bindings in its creation environment.
  2. Does it capture a snapshot? Not generally; it retains bindings whose values may change.
  3. How can closures cause leaks? Long-lived callbacks can keep captured objects and their reachable graph alive.
  4. How do you release a closure-related listener? Remove it or use a lifecycle/AbortSignal cleanup mechanism.
  5. What fixes the classic loop closure issue? Use a per-iteration lexical binding such as let or explicitly capture a value.

References