Problem Statement
What is a closure? Explain with examples and common use cases.
Explanation
Closure is created when an inner function remembers variables from its outer function scope even after the outer function has finished executing.
How closures work:
When you return a function from another function, the returned function carries its lexical environment with it. Variables from the outer function remain accessible to the inner function. The outer function's variables are kept alive in memory as long as the inner function exists.
Common use cases:
Data privacy and encapsulation. Creating private variables that cannot be accessed from outside. Factory functions that generate customized functions. Event handlers that need to remember state. Memoization for caching function results. Module pattern for organizing code.
Important points:
Closures can cause memory leaks if not managed properly. All inner functions share the same outer variables. Understanding closures is essential for advanced JavaScript.
Closures are one of the most important and frequently asked interview topics in JavaScript.
Code Solution
SolutionRead Only
// Basic closure example
function outer() {
let count = 0; // Private variable
return function inner() {
count++; // Accesses outer variable
return count;
};
}
const counter = outer();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// count is kept alive by closure
// Data privacy
function createPerson(name) {
let age = 0; // Private
return {
getName: function() {
return name;
},
getAge: function() {
return age;
},
birthday: function() {
age++;
}
};
}
const person = createPerson('John');
console.log(person.getName()); // 'John'
console.log(person.getAge()); // 0
person.birthday();
console.log(person.getAge()); // 1
// console.log(person.age); // undefined (private!)
// Function factory
function multiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
// Event handler with closure
function setupButtons() {
for (let i = 0; i < 3; i++) {
const button = document.createElement('button');
button.textContent = 'Button ' + i;
button.addEventListener('click', function() {
console.log('Button ' + i + ' clicked');
// i is remembered by closure
});
}
}
// Memoization
function memoize(fn) {
const cache = {}; // Private cache
return function(...args) {
const key = JSON.stringify(args);
if (key in cache) {
console.log('From cache');
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
const expensiveOperation = memoize((n) => {
console.log('Computing...');
return n * n;
});
console.log(expensiveOperation(5)); // Computing... 25
console.log(expensiveOperation(5)); // From cache 25