JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsjavascriptClosures
PrevNext
javascript
intermediate
12 min read

Closures

closures
data-privacy
functions
iife
module-pattern
scope
state

A closure is a function that retains access to variables from its outer (enclosing) scope even after the outer function has returned, enabled by JavaScript's lexical scoping.

Key Points

1Lexical Environment

A closure is a function bundled with a reference to its outer scope — it retains access to those variables even after the outer function returns.

2Data Privacy

Closures create truly private variables that can only be accessed through the returned functions, not directly from outside.

3Function Factories

Outer functions return specialized inner functions that remember the arguments passed to the outer function via the closure.

4The For-Loop Problem

var is function-scoped so loop callbacks share one variable; let creates a new binding per iteration, giving each callback its own copy.

5Module Pattern

An IIFE returns an object with methods that access private variables in the closure — the encapsulation pattern used before ES modules.

What You'll Learn

  • Explain what a closure is and how lexical scoping enables it
  • Use closures for data privacy, function factories, and state preservation
  • Solve the classic for-loop closure problem and explain why it occurs

Deep Dive

A closure is created when a function is defined inside another function and references variables from the outer function's scope. The inner function "closes over" those variables, keeping them alive in memory even after the outer function has finished executing. Every function in JavaScript forms a closure, but the term is most meaningful when an inner function outlives its outer function.

How Closures Work

JavaScript uses lexical scoping — variable access is determined by where functions are written in the source code, not where they are called. When a function is created, it gets a hidden reference to its lexical environment (the scope chain at the point of definition). When the function later executes and references a variable, JavaScript walks up this scope chain: local scope first, then each enclosing scope, up to the global scope.

Common Use Cases

Data privacy and encapsulation: Closures create truly private variables. A function can return an object with methods that access variables in the closure, but those variables cannot be accessed directly from outside. This was the primary encapsulation mechanism before ES modules and class private fields (#field).

Function factories: A function that returns a specialized function based on its arguments. For example, function makeMultiplier(x) { return y => x * y; } creates double = makeMultiplier(2) and triple = makeMultiplier(3) — each closure remembers its own x.

State preservation: Closures maintain state between calls without global variables. A counter function can keep its count in the closure, incrementing on each call while keeping the count inaccessible from outside.

Callbacks and event handlers: When you pass a function as a callback, it carries its closure with it, preserving access to surrounding variables at the time of creation.

The Classic For-Loop Problem

This is the most frequently asked closure interview question. With var in a for-loop, setTimeout callbacks all share the same i variable (function-scoped), so they all print the final value. With let, each iteration creates a new block-scoped i, so each callback captures its own copy. Before let existed, the fix was wrapping each iteration in an IIFE: (function(j) { setTimeout(() => console.log(j), 0); })(i).

The Module Pattern

Before ES modules, closures powered the module pattern: an IIFE returns an object exposing public methods while keeping internal state private in the closure. const counter = (function() { let count = 0; return { increment() { return ++count; }, value() { return count; } }; })(); — count is inaccessible from outside, but increment and value can read and modify it through the closure.

Memory Considerations

Closures keep their entire lexical environment alive as long as the inner function exists. This is usually fine, but can cause memory issues if a closure unintentionally captures a large object or DOM node that would otherwise be garbage collected. Modern engines like V8 optimize this by only retaining variables that the inner function actually references, but it's worth being aware of when debugging memory leaks.

Key Interview Distinction

A closure is not just a function — it's a function plus its lexical environment. The function remembers the variables from the scope where it was created, not where it is called. This is the fundamental concept that enables data privacy, state preservation, and the module pattern in JavaScript.

Fun Fact

The term 'closure' was coined by Peter Landin in 1964 to describe a function paired with its referencing environment — decades before JavaScript existed. JavaScript popularized closures in mainstream programming when Douglas Crockford championed them as the key to the module pattern.

Learn These First

Functions

beginner

Continue Learning

Currying & Partial Application

intermediate

Debounce & Throttle

intermediate

Memory Management & Garbage Collection

advanced

Practice What You Learned

What is a closure in JavaScript and why are they useful?
mid
closures
A closure is a function that has access to variables from its outer (enclosing) scope, even after the outer function has returned. They're useful for data privacy, state management, and creating function factories.
Previous
Promises & Async/Await
Next
Single Page Applications
PrevNext