Have you ever wondered how a function can remember variables even after the outer function has finished executing?
That's the magic of Closures in JavaScript!
** What is a Closure?**
A closure is created when a function remembers and can access variables from its outer lexical scope, even after the outer function has finished executing.
Real-World Example: Bank Account
Imagine creating a bank account. You want to deposit money and check the balance, but you don't want anyone to modify the balance directly.
function bankAccount() {
let balance = 1000;
return {
deposit(amount) {
balance += amount;
return balance;
},
getBalance() {
return balance;
}
};
}
const account = bankAccount();
console.log(account.getBalance()); // 1000
console.log(account.deposit(500)); // 1500
console.log(account.getBalance()); // 1500
console.log(account.balance); // undefined
How Does It Work?
bankAccount() creates a local variable called balance.
The function returns two inner functions: deposit() and getBalance().
Even after bankAccount() finishes executing, those functions retain access to balance.
The variable stays accessible through the returned functions without being directly exposed.
That's a closure! The inner functions remember the environment in which they were created.
Why Are Closures Important?
Closures are useful for:
- Data privacy and encapsulation
- Callbacks and event handlers
- Function factories
- Maintaining state between function calls
- Understanding hooks and other JavaScript patterns
** Key Takeaway**
A closure is not simply a function inside another function. It's a function together with access to its surrounding lexical environment.
Once you understand closures, many JavaScript concepts become easier to understand!
Question for developers: Where have you used closures in your projects?
Top comments (1)
Nice clear example. One thing worth adding for beginners: each call to bankAccount() creates its own separate balance, so you can make two independent accounts (const a = bankAccount(); const b = bankAccount();) and depositing into one won't affect the other. That's also the classic gotcha with
varin loops: all callbacks share one variable, whileletcreates a new binding per iteration, so closures capture a different value each time. Good tip for debugging is to log inside the inner function and see which value it actually sees.