Closures are one of those JavaScript concepts that are heard everywhere but often remain a mystery.
🔹 1. What is a Closure?
A closure is the combination of a function and the lexical environment within which that function was declared. Essentially, a closure has access to its outer function's scope, variables, and parameters, even after the outer function has finished executing.
🔹 2. How They Work (The "Memory" of Functions)
When a function is created, it "remembers" the environment (variables, parameters) where it was created. If this function is passed around or returned from another function, it carries that remembered environment with it.
Example:
function outerFunction() {
let outerVariable = "I'm from the outer scope";
function innerFunction() { // This is the closure
print(outerVariable); // It can still access outerVariable!
}
return innerFunction;
}
const myClosure = outerFunction(); // outerFunction finishes, but its scope is remembered
myClosure(); // Calling the inner function
Output:
I'm from the outer scope🔹 3. Common Use Cases
• Data Privacy (Private Variables): You can create functions that have access to "private" variables that cannot be accessed directly from the outside.
Example:
function createCounter() {
let count = 0; // Private variable
return function() { // The closure
count++;
print(count);
};
}
const counter1 = createCounter();
counter1(); // Output: 1
counter1(); // Output: 2
const counter2 = createCounter(); // Creates a *new* closure with its own 'count'
counter2(); // Output: 1
Notice
counter1 and counter2 have their own separate count.• Callback Functions: When you pass a function to another function (like
setTimeout or event handlers), it often forms a closure.• Currying & Partial Application: Advanced techniques where functions are transformed to return new functions.
🔹 4. The "Gotcha" (Loop Issue)
A classic mistake is using
var inside a for loop to create functions that reference loop variables. Because var has function scope, all closures created inside the loop end up referencing the *last* value of the loop variable.Example (The Problem):
// DON'T DO THIS with `var`
for (var i = 0; i < 3; i++) {
setTimeout(function() {
print(i); // Will print 3, 3, 3!
}, 100);
}
🔹 5. The Fix (Using
let or IIFEs)Using
let (which has block scope) or an Immediately Invoked Function Expression (IIFE) solves the loop issue by creating a new scope for each iteration.Example (The Fix with
let):for (let i = 0; i < 3; i++) { // 'let' creates a new 'i' for each loop
setTimeout(function() {
print(i); // Will correctly print 0, 1, 2!
}, 100);
}
🎯 What you should do
✔️ Understand that functions "remember" their creation environment
✔️ See how closures enable data privacy
✔️ Recognize and fix the common loop variable "gotcha"