What Is Closure in JavaScript?

Closures are one of the most important and most misunderstood concepts in JavaScript. If you work with callbacks, event handlers, React hooks, or async code, you are already using closures—whether you realize it or not.

This article explains closures from the ground up, with real-world examples, performance notes, and common pitfalls.


Closure Definition (In Simple Terms)

A closure is created when a function remembers and accesses variables from its outer scope, even after the outer function has finished executing.

In JavaScript:

  • Functions form closures automatically
  • No special syntax is required
  • Closures exist because of lexical scoping

Basic Closure Example

function outer() {
  let count = 0;

  function inner() {
    count++;
    return count;
  }

  return inner;
}

const counter = outer();

counter(); // 1
counter(); // 2
counter(); // 3

What’s Happening Internally?

  • outer() executes and returns inner
  • count should be destroyed after outer() finishes
  • But inner() closes over count
  • JavaScript keeps count alive in memory

This preserved scope is the closure.


Why Closures Exist in JavaScript

Closures exist because JavaScript uses lexical scoping, meaning:

  • Scope is determined at write-time, not run-time
  • Inner functions can access outer variables

This behavior enables:

  • Data privacy
  • State preservation
  • Functional programming patterns

Real-World Use Cases of Closures

1. Data Encapsulation (Private Variables)

function createUser(name) {
  let isLoggedIn = false;

  return {
    login() {
      isLoggedIn = true;
    },
    status() {
      return isLoggedIn;
    }
  };
}

const user = createUser('Alex');
user.login();
user.status(); // true

No external code can directly access isLoggedIn.


2. Callbacks and Event Handlers

function attachHandler(buttonId) {
  const clickCount = 0;

  document.getElementById(buttonId)
    .addEventListener('click', function () {
      console.log(clickCount);
    });
}

The event handler keeps access to clickCount through closure.


3. setTimeout and Async Code

function delayedMessage(msg) {
  setTimeout(() => {
    console.log(msg);
  }, 1000);
}

delayedMessage('Hello');

Even after delayedMessage() finishes, msg remains accessible.


Closure vs Scope (Quick Comparison)

AspectScopeClosure
When definedAt function/block creationAt function execution
PurposeVariable visibilityPreserve outer variables
MemoryReleased after executionRetained if referenced

Common Closure Mistake (Loop Issue)

for (var i = 1; i <= 3; i++) {
  setTimeout(() => console.log(i), 1000);
}

Output: 4 4 4

Why This Happens

  • var is function-scoped
  • One shared i is closed over
  • Loop finishes before setTimeout runs

Fix Using let

for (let i = 1; i <= 3; i++) {
  setTimeout(() => console.log(i), 1000);
}

let creates a new binding per iteration.


Memory Considerations with Closures

Closures can increase memory usage if misused.

Potential Issues

  • Long-lived references
  • Unreleased DOM elements
  • Large objects kept alive unnecessarily

Best Practices

  • Avoid closing over large objects
  • Remove event listeners when not needed
  • Nullify references when done

Closures in Modern JavaScript Frameworks

React

  • Hooks rely heavily on closures
  • useEffect captures variables
  • Stale closure bugs are common

Node.js

  • Closures maintain request state
  • Used in middleware and callbacks

Closures are foundational—not optional knowledge.


Performance Comparison Table

ApproachMemory UsageReadabilityUse Case
Global variablesHigh riskLowAvoid
Class-based stateMediumMediumLarge systems
Closure-based stateControlledHighFunctional patterns

Summary

  • Closures allow functions to remember outer variables
  • They are created automatically in JavaScript
  • Used in callbacks, async code, and frameworks
  • Powerful but must be handled carefully

Understanding closures unlocks advanced JavaScript patterns.


Frequently Asked Questions (FAQ)

What is a closure in JavaScript?

A closure is a function that retains access to variables from its outer scope even after that scope has finished executing.

Are closures created manually?

No. Closures are created automatically whenever a function accesses outer variables.

Do closures cause memory leaks?

They can if references are kept unnecessarily. Proper cleanup prevents issues.

Are closures used in React?

Yes. Hooks like useEffect and useCallback depend on closures.


Share via
Copy link