A closure is created when a function remembers variables from its outer scope even after the outer function has finished executing. This is one of the most important JavaScript interview topics and is frequently asked in frontend interviews.
Question 1
function outer() {
let count = 10;
function inner() {
console.log(count);
}
inner();
}
outer();
The inner function can access variables from the outer function.
Question 2
function outer() {
let count = 10;
return function() {
console.log(count);
};
}
const fn = outer();
fn();
The returned function remembers count even after outer() finishes.
Question 3
function outer() {
let value = 5;
return function() {
return value;
};
}
console.log(outer()());
The closure keeps access to value.
Question 4
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter());
console.log(counter());
The closure preserves state between calls.
Question 5
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const c1 = createCounter();
const c2 = createCounter();
console.log(c1());
console.log(c2());
Each closure gets its own private state.
Question 6
function outer() {
let value = 10;
return function() {
value += 5;
return value;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
The closure updates and remembers the variable.
Question 7
function outer() {
let name = "John";
return function() {
return name;
};
}
const getName = outer();
console.log(getName());
The closure remembers the outer variable.
Question 8
function outer() {
let count = 1;
return function() {
count++;
return count;
};
}
const fn = outer();
fn();
console.log(fn());
The first call makes count 2. The second call makes it 3.
Question 9
function outer() {
let a = 10;
return function() {
let b = 20;
return a + b;
};
}
console.log(outer()());
The inner function uses both variables.
Question 10
function outer() {
let value = 10;
return function() {
console.log(value);
};
}
const fn1 = outer();
const fn2 = outer();
fn1();
fn2();
Each call creates a new closure.
Question 11
function outer() {
let score = 100;
return function() {
score -= 10;
return score;
};
}
const fn = outer();
console.log(fn());
The closure can modify outer variables.
Question 12
function outer() {
let x = 1;
return function() {
return ++x;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
The value persists across calls.
Question 13
function outer() {
let message = "Hello";
function inner() {
console.log(message);
}
return inner;
}
outer()();
The returned function still remembers message.
Question 14
function outer() {
let a = 5;
return function() {
return a * 2;
};
}
console.log(outer()());
The closure uses the outer variable in calculations.
Question 15
function createUser(name) {
return function() {
return name;
};
}
const user = createUser("Peter");
console.log(user());
The parameter is preserved through closure.
Question 16
function outer() {
let value = 100;
return function() {
return value;
};
}
const fn = outer();
value = 500;
console.log(fn());
The closure uses the variable from outer(), not a global variable.
Question 17
function outer() {
let count = 0;
return function() {
return count++;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
Post-increment returns the current value before increasing it.
Question 18
function outer() {
let a = 1;
return function() {
return function() {
return a;
};
};
}
console.log(outer()()());
Closures can exist across multiple nested functions.
Question 19
function outer() {
let count = 10;
return function() {
count--;
return count;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
The value is updated and remembered.
Question 20
function outer() {
let value = 50;
return {
getValue() {
return value;
}
};
}
console.log(outer().getValue());
Methods can also form closures over outer variables.
Question 21
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
All callbacks share the same variable i.
Question 22
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
Each iteration gets its own closure.
Question 23
for (var i = 0; i < 3; i++) {
((x) => {
setTimeout(() => console.log(x), 0);
})(i);
}
The IIFE creates a separate closure for each value.
Question 24
function outer() {
let count = 0;
return {
increment() {
count++;
},
getCount() {
return count;
}
};
}
const counter = outer();
counter.increment();
console.log(counter.getCount());
Both methods share the same closure.
Question 25
function outer() {
let count = 0;
return {
increment() {
count++;
},
decrement() {
count--;
},
getCount() {
return count;
}
};
}
const obj = outer();
obj.increment();
obj.increment();
obj.decrement();
console.log(obj.getCount());
All methods operate on the same variable.
Question 26
function createCounter() {
let count = 0;
return () => ++count;
}
const c1 = createCounter();
const c2 = createCounter();
console.log(c1());
console.log(c1());
console.log(c2());
Each counter has its own private state.
Question 27
function outer(name) {
return function() {
return name;
};
}
const a = outer("John");
const b = outer("Peter");
console.log(a());
console.log(b());
Each closure stores its own parameter value.
Question 28
function outer() {
let value = 10;
return function() {
value += 10;
return value;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
console.log(fn());
The closure preserves changes between calls.
Question 29
function outer() {
let value = 100;
return {
get() {
return value;
}
};
}
const obj = outer();
console.log(obj.get());
The method closes over the outer variable.
Question 30
function outer() {
let secret = "JS";
return {
getSecret() {
return secret;
}
};
}
const obj = outer();
console.log(obj.secret);
The variable is private and not exposed directly.
Question 31
function outer() {
let count = 0;
return {
increment() {
count++;
},
get() {
return count;
}
};
}
const a = outer();
const b = outer();
a.increment();
console.log(a.get());
console.log(b.get());
Each closure maintains separate data.
Question 32
function outer(a) {
return function(b) {
return a + b;
};
}
console.log(outer(5)(3));
The inner function remembers a.
Question 33
function outer(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(outer(1)(2)(3));
Closures can span multiple nested levels.
Question 34
function createCounter() {
let count = 0;
return () => count++;
}
const counter = createCounter();
console.log(counter());
console.log(counter());
Post-increment returns the current value first.
Question 35
function outer() {
let value = 5;
return function() {
value *= 2;
return value;
};
}
const fn = outer();
console.log(fn());
console.log(fn());
The closure keeps the updated value.
Question 36
function outer() {
let value = 1;
return function() {
return ++value;
};
}
const a = outer();
const b = outer();
console.log(a());
console.log(b());
Each closure starts with its own value variable.
Question 37
function outer() {
let name = "JavaScript";
return () => name.length;
}
console.log(outer()());
"JavaScript" contains 10 characters.
Question 38
function outer() {
let count = 0;
return {
inc() {
count++;
},
value() {
return count;
}
};
}
const obj = outer();
obj.inc();
obj.inc();
console.log(obj.value());
The closure stores the updated count.
Question 39
function outer() {
let a = 10;
return function() {
return function() {
return a;
};
};
}
const fn = outer();
console.log(fn()());
The innermost function still remembers a.
Question 40
function createCounter(start) {
return function() {
return ++start;
};
}
const counter = createCounter(5);
console.log(counter());
console.log(counter());
Parameters are also preserved by closures.