Closures in JavaScript
Closures can be a confusing subject. But before we get into exactly what closures are, we should refresh our knowledge of scope since it's linked to closures.
Scope
Generally, scope works from inside to outside. So inside a function the function has access to its own local variables, and all variables in outer scopes - ie. global objects. But it won’t have access to variables that reside inside other functions - unless it’s nested inside another function, then it has access to its parent’s scope (and its parents, etc.). Let’s look at an example:
let globalVariable = "I'm global!";
function myFunction() {
let localVariable = "I'm local to myFunction!";
function insideFunction() {
let innerVariable = "I'm in insideFunction!";
console.log(innerVariable); // "I'm in insideFunction!";
console.log(localVariable); // "I'm local to myFunction!";
console.log(globalVariable); // "I'm global!";
}
}
So insideFunction has access to the variables inside itself, and the parent myFunction, and finally the global scope (ie.globalVariable
). But it doesn’t work from the outside in. Out in the global scope you can’t console.log
neither localVariable
(in myFunction) or innerVariable
(in insideFunction):
console.log(innerVariable);
// "ReferenceError: innerVariable is not defined" since it's inside a function and not available in global scope
Closures
Closure basically means that a function does not lose connection to the variables that existed when the function was created. Let’s look at an example of how this works:
function counterFunction() {
let count = 0;
return function () {
count += 1;
console.log(`Count is now ${count}`);
};
}
let result = counterFunction();
result(); // "Count is now 1"
result(); // "Count is now 2"
result(); // "Count is now 3"
As you can see in the above example, the result
function still has access to the count
variable created inside counterFunction
, even though that function has finished executing. It works because counterFunction
returned a new function, which closes over its parent function and keeps access to its variables, even after the parent function is done executing. That’s how we’re able to use result
to increase the count
variable.
Summary
We have seen how scope works from inside to outside, and how a function closure preserves the outer scope inside its inner scope.