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()); // 3That'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:
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.