What is a closure?
A closure is the combination of a function and the environment it was created in. When you create a function inside another function, the inner function keeps a reference to the scope it was defined in, so it can still read those variables after the outer function has returned.
function createCounter() {
let count = 0;
return {
increment() {
count += 1;
return count;
},
get value() {
return count;
},
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.value); // 2
const other = createCounter();
console.log(other.value); // 0 - a separate closure, separate stateThe word closure sounds grander than it is. Every function in JavaScript has one. The interesting case is when the function outlives the scope it was written in, because then the variables it captured stay alive instead of being collected.
Two properties make closures powerful. The captured variables are private, so nothing outside can reach in and change them except through the functions you chose to expose. And each call of the outer function creates a fresh set of captured variables, which is why the two counters above are independent.
The cost is memory. A closure keeps its captured environment alive for as long as the function does, so a long-lived callback can hold onto a large object that you thought you had released. This is a real cause of memory leaks in long-running applications, and it is why it is worth thinking about what a callback really holds on to.