Why you should understand closure in Javascript
Definitely NOT because it’s a common interview question, but because it’s one of the most useful and powerful features of Javascript.
Every time a function is invoked, the Javascript engine creates a brand new execution context with memory that goes away as soon as the function finishes executing, and is removed from the call stack.
Closure makes it possible for a function to have persisting state. This feature alone enables memoization, partial application, the module pattern and React Hooks, to name a few.
In simple terms, let’s say that in order for a function to have persisting state, it must be created and returned from another function. Let’s look at a simple example:
function makeCounter() {
let count = 0
return function counter() {
return count++
}
}
const counter = makeCounter()
counter() // 0
counter() // 1
counter() // 2
Note that count
is persisted between function calls, and the counter
function still has a reference to it even after makeCounter
has finished executing.
Now that we know how to persist state between function calls, let’s look at a more useful use of closure. Let’s create a simplified history feature so users can optionally undo actions on an application.
function makeHistory(limit) {
function makeStack() {
// note that both push and pop have a persiting ref. to data
const data = []
function push(action) {
if (data.length < limit) {
data.unshift(action)
}
}
function pop() {
return data.length === 0 ? undefined : data.shift()
}
return { push, pop }
}
const history = makeStack()
// act has a persisting reference to history
return function act(action) {
if (action === "undo") {
const popped = history.pop()
return popped ? `${popped} undone` : "nothing to undo"
}
history.push(action)
return `${action} done`
}
}
const act = makeHistory(2)
act("get") // 'get done'
act("undo") // 'get undone'
act("create") // 'create done'
act("update") // 'update done'
act("delete") // 'delete done'
act("undo") // 'update undone'
act("undo") // 'create undone'
act("undo") // 'nothing to undo'
Thanks for reading! Have something to say? Please, leave a comment!