Question 1
function createCounter() {
let count = 0;
return {
increment() {
count++;
},
getCount() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount());
The variable remains private and is accessible only through returned methods.
Question 2
function createCounter() {
let count = 0;
return {
increment() {
count++;
}
};
}
const counter = createCounter();
console.log(counter.count);
count is not exposed as an object property.
Question 3
function createMultiplier(multiplier) {
return function(value) {
return value * multiplier;
};
}
const double = createMultiplier(2);
console.log(double(5));
The returned function remembers the multiplier value.
Question 4
function createMultiplier(multiplier) {
return function(value) {
return value * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(4));
console.log(triple(4));
Each factory call creates a separate closure instance.
Question 5
function createUser(name) {
return {
getName() {
return name;
}
};
}
const user = createUser("John");
console.log(user.getName());
The closure provides controlled access to private data.
Question 6
function createUser(name) {
return {
getName() {
return name;
}
};
}
const user = createUser("John");
user.name = "Peter";
console.log(user.getName());
The private variable and object property are different values.
Question 7
function createBankAccount(balance) {
return {
deposit(amount) {
balance += amount;
},
getBalance() {
return balance;
}
};
}
const account = createBankAccount(100);
account.deposit(50);
console.log(account.getBalance());
The closure preserves and updates internal state.
Question 8
function createBankAccount(balance) {
return {
withdraw(amount) {
balance -= amount;
},
getBalance() {
return balance;
}
};
}
const account = createBankAccount(200);
account.withdraw(50);
console.log(account.getBalance());
The same internal variable is shared across methods.
Question 9
function createIdGenerator() {
let id = 0;
return {
next() {
return ++id;
}
};
}
const gen = createIdGenerator();
console.log(gen.next());
console.log(gen.next());
The closure preserves state between calls.
Question 10
function createIdGenerator() {
let id = 0;
return {
next() {
return ++id;
}
};
}
const a = createIdGenerator();
const b = createIdGenerator();
console.log(a.next());
console.log(a.next());
console.log(b.next());
Each generator owns its own private state.
Question 11
function createToggle() {
let value = false;
return {
toggle() {
value = !value;
return value;
}
};
}
const t = createToggle();
console.log(t.toggle());
console.log(t.toggle());
The closure keeps track of previous state.
Question 12
function createModule() {
let secret = "JS";
return {
reveal() {
return secret;
}
};
}
const module = createModule();
console.log(module.reveal());
This is a classic module-pattern interview question.
Question 13
function createModule() {
let secret = "JS";
return {
reveal() {
return secret;
}
};
}
const module = createModule();
console.log(module.secret);
Private variables cannot be accessed directly.
Question 14
function createAdder(x) {
return function(y) {
return x + y;
};
}
const add10 = createAdder(10);
console.log(add10(5));
The closure remembers the original argument.
Question 15
function createAdder(x) {
return function(y) {
return x + y;
};
}
const add5 = createAdder(5);
const add20 = createAdder(20);
console.log(add5(1));
console.log(add20(1));
Each returned function has its own preserved environment.
Question 16
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs[0]();
All functions share the same variable i. After the loop ends, i becomes 3.
Question 17
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs[0]();
funcs[1]();
funcs[2]();
Every function closes over the same i variable.
Question 18
var funcs = [];
for (let i = 0; i < 3; i++) {
funcs.push(function() {
console.log(i);
});
}
funcs[0]();
funcs[1]();
funcs[2]();
let creates a new binding for each loop iteration.
Question 19
var funcs = [];
for (var i = 0; i < 3; i++) {
(function(value) {
funcs.push(function() {
console.log(value);
});
})(i);
}
funcs[2]();
The IIFE captures the current value of i.
Question 20
var funcs = [];
for (var i = 0; i < 2; i++) {
funcs.push(function() {
return i;
});
}
console.log(funcs[0]());
The loop finishes before the function executes.
Question 21
function build() {
var result = [];
for (let i = 1; i <= 3; i++) {
result.push(function() {
return i;
});
}
return result;
}
const arr = build();
console.log(arr[1]());
Each function remembers its own loop binding.
Question 22
function createFunctions() {
const result = [];
for (var i = 1; i <= 3; i++) {
result.push(function() {
return i;
});
}
return result;
}
const arr = createFunctions();
console.log(arr[0]());
The loop ends with i equal to 4.
Question 23
function createCounter() {
let count = 0;
return {
inc() {
count++;
},
dec() {
count--;
},
get() {
return count;
}
};
}
const c = createCounter();
c.inc();
c.inc();
c.dec();
console.log(c.get());
All methods share the same private variable.
Question 24
function createCounter() {
let count = 0;
return function() {
return ++count;
};
}
const a = createCounter();
const b = createCounter();
console.log(a());
console.log(b());
Each counter owns separate state.
Question 25
function outer() {
let value = 10;
return {
get() {
return value;
},
set(v) {
value = v;
}
};
}
const obj = outer();
obj.set(50);
console.log(obj.get());
Both methods share the same closure state.
Question 26
function createLogger(msg) {
return function() {
return msg;
};
}
const logA = createLogger("A");
const logB = createLogger("B");
console.log(logA());
console.log(logB());
Each closure preserves its own argument.
Question 27
let value = 100;
function create() {
return function() {
return value;
};
}
const fn = create();
value = 500;
console.log(fn());
Closures capture variables, not copied values.
Question 28
function create() {
let data = [];
return {
add(v) {
data.push(v);
},
size() {
return data.length;
}
};
}
const store = create();
store.add(1);
store.add(2);
console.log(store.size());
The array is maintained inside the closure.
Question 29
function factory(x) {
return function(y) {
return function(z) {
return x + y + z;
};
};
}
console.log(factory(1)(2)(3));
Each nested function preserves access to outer parameters.
Question 30
function create() {
let count = 0;
return {
inc() {
count++;
},
reset() {
count = 0;
},
get() {
return count;
}
};
}
const c = create();
c.inc();
c.inc();
c.reset();
console.log(c.get());
All methods operate on the same private variable.
Question 31
for (var i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
All callbacks share the same var variable. The loop completes before the timers run.
Question 32
for (let i = 0; i < 3; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
let creates a new binding for every iteration.
Question 33
for (var i = 0; i < 3; i++) {
((value) => {
setTimeout(() => {
console.log(value);
}, 0);
})(i);
}
The IIFE captures the current loop value.
Question 34
function memoize(fn) {
const cache = {};
return function(n) {
if (cache[n]) {
return cache[n];
}
cache[n] = fn(n);
return cache[n];
};
}
const square = memoize(x => x * x);
console.log(square(4));
console.log(square(4));
The cached value is returned on the second call.
Question 35
function add(a) {
return function(b) {
return a + b;
};
}
console.log(add(5)(10));
The inner function remembers the first argument.
Question 36
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(8));
This is a partial application pattern.
Question 37
function curry(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(curry(1)(2)(3));
Each function preserves the arguments supplied earlier.
Question 38
function once(fn) {
let called = false;
return function() {
if (!called) {
called = true;
return fn();
}
};
}
const greet = once(() => "Hello");
console.log(greet());
console.log(greet());
The closure remembers whether the function has already been executed.
Question 39
function createCounter() {
let count = 0;
return () => ++count;
}
const counter = createCounter();
console.log(counter());
console.log(counter());
console.log(counter());
The arrow function preserves and updates the same variable.
Question 40
function createStore() {
let data = [];
return {
add(item) {
data.push(item);
},
getAll() {
return data.length;
}
};
}
const store = createStore();
store.add("A");
store.add("B");
console.log(store.getAll());
The closure manages private collection state.
Question 41
function compose(f, g) {
return function(x) {
return f(g(x));
};
}
const add1 = x => x + 1;
const double = x => x * 2;
console.log(compose(add1, double)(5));
double(5) becomes 10, then add1(10) becomes 11.
Question 42
function createMultiplier(factor) {
return value => value * factor;
}
const triple = createMultiplier(3);
console.log(triple(7));
The arrow function captures factor through closure.
Question 43
function delayMessage(msg) {
return function() {
console.log(msg);
};
}
const fn = delayMessage("JS");
fn();
The returned function retains access to msg.
Question 44
function factory(start) {
let value = start;
return {
increase() {
value++;
},
current() {
return value;
}
};
}
const obj = factory(10);
obj.increase();
obj.increase();
console.log(obj.current());
The object methods share the same private variable.
Question 45
function createSecret(secret) {
return {
reveal() {
return secret;
}
};
}
const obj = createSecret("Frontend");
console.log(obj.reveal());
The secret remains private and is accessible only through the closure.