Understanding JavaScript Closures

I first learned about closures before starting my coding bootcamp and thought I had a general handle on the concept. Then I learned about them for a second time in my course and felt more confused than I was before. I decided to write a post to solidify my understanding of the subject (third time’s a charm, I guess?). The thing is – closures aren’t as complicated as they seem and they allow you to write some cool, creative, and efficient code. I think the key to understanding closures is to practice with examples and play around with the code until you have a good idea of what is going to return and why. This is good practice for understanding all coding concepts, but I think many explanations of closures have these lofty, conceptual descriptions that are confusing and make everything seem more complicated than it actually is.

What Are Closures?

At a basic level, you create a closure when you use the function keyword inside another function. That inner function then has access to the outer function’s variables and parameters. Remember that JavaScript variables have reference to their entire outer scope, so the inner function having access to the outer functions’ scope(s) makes sense. A way to conceptualize closure is to picture a function that ‘closes over’ some local variable.

To summarize, a closure has three scope chains. It has access to:

Its own scope (the inner function’s variables)

The outer function’s variables and parameters

Global variables (window environment)

Here is a simple example of a closure:

Here’s what’s happening:

We can see the inner function’s scope:

And the outer function’s scope:

And the global scope!:

Now what happens when we add a variable to the inner function?

JavaScript doesn’t like that! We’re getting an error because the outer function (sayHi) does not know about the inner function’s scope.

How Does This Work?

In a closure, functions remember the environment in which they were created and maintain references to variables in that environment. When JavaScript functions execute, they use the same scope chain that was in effect when they were created. The fun thing about closures is that the inner function still has access to the outer function’s variables even after the outer function has been called. Therefore, you can call the inner function later in the code.

The inner function also has access to the outer function’s parameters, however, the inner function cannot access the outer function’s arguments object. It can only access the outer function’s parameters directly. (The arguments object is an array-like object corresponding to the arguments passed to a function. Each scope can only have one arguments object. Read more about arguments object here.) Along the same lines, closures store references to the outer function’s variables, but they do not store actual values.

Fun fact: we can do all this because JavaScript has first class functions. From Wikipedia:

The language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.

Why Are Closures Necessary?

JavaScript operates around two circumstances:

1. A scope is mostly created at the function level (more on that below). They aren’t created by while/for loops or by if statements, like other languages. Closures provide us with more access and functionality.

2. JavaScript, in practice, is event-driven and asynchronous. Closures make event-driven code easier to write – we can make a single function which is executed in response to an event.

A Quick Note On Scopes

JavaScript used to only have two types of scope: function scope and global scope. With the new version of JavaScript, the let statement allows you to declare variables that are limited to the block, statement, or expression for which it’s used. In this example, there are no functions to be seen; the curly braces {…} define a new scope for the variable x.