Closures

Closures

Modern JavaScript Series

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.