JavaScript Closures Explained with Examples - Interview Question
Closures
Closures are one of the most important concepts in JavaScript. A closure is created when a function remembers variables from its outer lexical scope, even after the outer function has finished executing. In simple terms, an inner function can continue to use variables declared in its parent function.
Closures exist because JavaScript uses lexical scoping. That means the scope of a variable is determined by where it is written in the code, not where the function is called from. When a function is returned or passed elsewhere, it still keeps access to the variables that were available when it was created.
Why Closures Matter
Closures are used everywhere in modern JavaScript. They help us preserve state, create private data, build reusable function factories, and write cleaner event handlers and callbacks.
function outerFunction() {
const message = 'Hello from the outer function';
function innerFunction() {
console.log(message);
}
return innerFunction;
}
const fn = outerFunction();
fn(); // Hello from the outer function
In the example above, innerFunction() is returned from outerFunction(). Even though outerFunction() has already finished, innerFunction() still remembers the variable message. That remembered scope is the closure.
Closures and Private State
One of the most common uses of closures is to create private state. This is useful when you want to hide implementation details and expose only a small public API.
function createCounter() {
let count = 0;
return {
increment() {
count++;
return count;
},
decrement() {
count--;
return count;
},
getValue() {
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getValue()); // 2
console.log(counter.count); // undefined
Here, count cannot be accessed directly from outside the function, but the returned methods still have access to it. This is a classic closure-based pattern for data privacy.
Function Factory with Closures
Closures are also useful for creating function factories. A factory function creates and returns another function with some preconfigured behavior.
function multiplyBy(multiplier) {
return function(number) {
return number * multiplier;
};
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
double() and triple() each preserve their own multiplier. That is why the same factory function can produce functions with different behavior.
Closures in Loops
Closures inside loops can be tricky. If you use var, every callback may end up sharing the same variable. Using let creates a new binding for each loop iteration.
// Problem with var
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log('var:', i);
}, 100);
}
// Correct with let
for (let j = 1; j <= 3; j++) {
setTimeout(function() {
console.log('let:', j);
}, 100);
}
// Output:
// var: 4
// var: 4
// var: 4
// let: 1
// let: 2
// let: 3
Real-World Uses of Closures
function memoizeSquare() {
const cache = {};
return function(num) {
if (cache[num] !== undefined) {
console.log('From cache');
return cache[num];
}
console.log('Calculated');
cache[num] = num * num;
return cache[num];
};
}
const square = memoizeSquare();
console.log(square(5)); // Calculated -> 25
console.log(square(5)); // From cache -> 25
Closures vs Scope
A closure is not a separate feature from scope. It is the result of normal lexical scoping plus functions being treated as first-class values. Every closure depends on scope, but not every scope usage becomes a closure. A closure happens when a function continues using outer variables after the outer function has completed.
Level Up Your Javascript Skills
Master Javascript with these hand-picked resources