What is a closure in JavaScript?

A closure is a function that remembers the variables from the scope where it was created, even after that scope has finished executing.

JavaScript

Overview

A closure is formed when a function is defined inside another function and references variables from the outer function's scope. The inner function "closes over" those variables and can access them even after the outer function has returned.

Key Points

  • •Every function in JavaScript is a closure it retains access to its lexical scope.
  • •Common use: factory functions, private variables, callbacks, and event handlers.
  • •The classic closure loop bug: using `var` in a `for` loop shares one variable use `let` or IIFE to fix.
  • •Closures hold references, not copies if the outer variable changes, the closure sees the update.
  • •Memory: closures keep outer variables alive as long as the closure itself is referenced.

Examples

Counter with private state via closure

javascript
function makeCounter() {
  let count = 0; // private to this scope
  return {
    increment() { count++; },
    decrement() { count--; },
    value()     { return count; },
  };
}

const counter = makeCounter();
counter.increment();
counter.increment();
console.log(counter.value()); // 2
// count is not accessible outside closure provides privacy

Factory function using closure

javascript
function multiplier(factor) {
  return (number) => number * factor; // closes over 'factor'
}

const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15

Classic loop bug with var vs let fix

javascript
// Bug: all callbacks share the same 'i' (var is function-scoped)
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 3, 3, 3
}

// Fix: use let (block-scoped each iteration gets its own 'i')
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 0, 1, 2
}

Pro Tip

Closures are the foundation of most JavaScript patterns: module pattern, currying, memoisation, and React hooks. Once you understand that "functions remember where they were born," closures become intuitive.