Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Closures in JavaScript

Closures in JavaScript

~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

Closures are one of the most powerful – and initially most confusing – concepts in JavaScript. We'll use one to build a "private" account balance for our budget app, accessible only through controlled functions.

What is a closure?

A closure forms when a function retains access to variables from its SURROUNDING scope – even AFTER the outer function has already finished. The inner function essentially "closes over" those variables:

function createCounter() {
  let count = 0; // 'count' lives in createCounter's scope

  return function () {
    count++; // accesses 'count' from the SURROUNDING scope
    return count;
  };
}

const counter = createCounter(); // createCounter() has already FINISHED running

console.log(counter()); // 1
console.log(counter()); // 2 - 'count' 'survived', even though createCounter() returned long ago!
console.log(counter()); // 3

That's the core of a closure: the returned inner function keeps a LIVE reference to count, not just a copy of the value at the moment it was returned.

Practical example: a private account balance

Let's now build an "account factory" for our budget app – the balance itself isn't directly reachable from OUTSIDE, it can only be changed through the returned functions:

src/index.js
function createAccount(startingBalance) {
  let balance = startingBalance; // 'private' - not directly accessible from outside

  return {
    deposit(amount) {
      balance += amount;
      return balance;
    },
    withdraw(amount) {
      if (amount > balance) {
        throw new Error('Insufficient funds');
      }
      balance -= amount;
      return balance;
    },
    getBalance() {
      return balance;
    },
  };
}

const account = createAccount(1500);
console.log(account.getBalance()); // 1500

account.deposit(300);
account.withdraw(850);
console.log(account.getBalance()); // 950

console.log(account.balance); // undefined - no direct access possible!

Tipp: This pattern is called the "module pattern" – before real classes with private fields existed (chapters 19/14 of the TypeScript tutorial), this was, for years, the standard way to simulate "private" data in JavaScript.

Closures in loops: revisiting the let trap

The var loop trap from chapter 15 is actually a closure phenomenon: all callback functions created with var share the same closure over the same, single i variable. With let, each iteration gets a FRESH binding – and thus its own closure.

A brief warning: closures and memory

Achtung: As long as a closure exists (e.g. stored as a returned function), ALL variables it references stay in memory – they can't be removed by the garbage collector. With long-lived closures capturing large data structures, this can lead to memory leaks. Irrelevant for our small budget app, but a known pitfall in long-running Node.js servers.