A closure is a function bundled with the variables of the scope where it was created — it keeps them alive even after that scope has returned.
The basic example
function makeCounter() {
let count = 0; // private: only the returned functions can see it
return {
increment: () => ++count,
decrement: () => --count,
value: () => count,
};
}
const a = makeCounter();
const b = makeCounter(); // independent environment
a.increment(); a.increment(); a.increment();
b.decrement();
console.log(a.value(), b.value(), a.count);3 -1 undefinedWhat closures are used for
const makeMultiplier = (factor) => (n) => n * factor;
const double = makeMultiplier(2), triple = makeMultiplier(3);
console.log(double(5), triple(5));
function once(fn) {
let done = false, result;
return (...args) => {
if (!done) { done = true; result = fn(...args); }
return result;
};
}
const init = once(() => { console.log("initialising…"); return 42; });
console.log(init(), init());10 15
initialising…
42 42Closures capture variables, not values
let message = "first";
const say = () => message;
message = "second";
console.log(say()); // reads the variable's CURRENT valuesecondThe loop + closure interview classic
for (var i = 1; i <= 3; i++) {
setTimeout(() => console.log("var:", i), 0);
}
for (let j = 1; j <= 3; j++) {
setTimeout(() => console.log("let:", j), 0);
}
// pre-ES6 fix: an IIFE creates a new scope per iteration
for (var k = 1; k <= 3; k++) {
((k) => setTimeout(() => console.log("iife:", k), 0))(k);
}var: 4
var: 4
var: 4
let: 1
let: 2
let: 3
iife: 1
iife: 2
iife: 3Module pattern with an IIFE
const bank = (function () {
let balance = 0; // private
function log(msg) { return `[bank] ${msg}`; } // private
return {
deposit(amount) { balance += amount; return log(`+${amount}`); },
get balance() { return balance; },
};
})();
console.log(bank.deposit(50), bank.balance, bank.log);[bank] +50 50 undefinedWhat is a closure? Give a practical use.
Why does the var loop print 4, 4, 4?