Codectionary / Developer documentation / JavaScript

Closures

A closure is a function that remembers and can access variables from its outer (enclosing) scope, even after that outer function has finished executing. Closures happen automatically whenever a function is defined inside another function. They are the mechanism behind private state, function factories, and many common JavaScript patterns.

Syntax

function outer() {
  let value = 0;
  return function inner() { return value; };
}

Examples

Basic Closure

An inner function retaining access to its outer function's variable.

function makeCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3 - count persists between calls

Private State with Closures

Using a closure to create genuinely private variables before class private fields existed.

function createBankAccount(initialBalance) {
  let balance = initialBalance; // not accessible from outside

  return {
    deposit(amount) {
      balance += amount;
      return balance;
    },
    withdraw(amount) {
      if (amount > balance) {
        console.log("Insufficient funds");
        return balance;
      }
      balance -= amount;
      return balance;
    },
    getBalance() {
      return balance;
    }
  };
}

const account = createBankAccount(100);
console.log(account.deposit(50));  // 150
console.log(account.withdraw(30)); // 120
// balance itself cannot be accessed or modified directly from outside

Function Factories

Using closures to generate specialized functions.

function multiplyBy(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = multiplyBy(2);
const triple = multiplyBy(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

Best practices

  • Use closures to create private state that cannot be accessed or mutated from outside a function
  • Be aware that closures keep their referenced variables alive in memory - avoid creating unnecessary closures in hot code paths or long-lived loops
  • Use closures for function factories and configurable, reusable function generators
  • Remember that each call to an outer function creates a new, independent closure - they do not share state with each other

At a glance

Purpose
Application logic and interaction
File extension
.js ยท .mjs
Runs in
Browsers and JavaScript runtimes
Usually used with
HTML, CSS and Web APIs

Specifications & further reading

Related JavaScript documentation