What’s a closure?

Closures are a key aspect of JavaScript that every developer should know about and understand. Today’s article merely skims the surface of closures, but will give you a good idea of what closures are and how they work in JavaScript. Lets jump in…

We’ll start by taking a peek at two textbook definitions of closure.

Definition #1:

A closure is a function that has access to the parent scope, even after the scope has closed.

Definition #2:

A closure is the combination of a function and the lexical environment within which that function was declared.

Great. But what do those actually mean?

First you need to understand scope in JavaScript. Scope is essentially the lifespan of a variable in JavaScript. You see, where a variable is defined plays a large role in how long that variable is around, and which functions in your program have access to it.

Lets look at an example.

When you create a function in JavaScript, it has access to variables created inside and outside the function.

Variables created inside a function are locally defined variables. A local variable can only be accessed within the function (scope) that it is defined in. In the example below, you’ll see that if we try to log the value of words outside of the function we get a reference error. That’s because words is a locally scoped variable:

Contrast that to this example where we define words in the global scope. This means it’s accessible to every function in the document:

Nested Functions

What happens when we nest one function inside of another? I want you to follow along with this next example because this is where it gets fun!

If you’re using Google Chrome, open up your developer console with [WINDOWS]: Ctrl + Shift + J [MAC]: Cmd + Opt + J

Cool. Now copy and paste the below code into your console. All we’ve done is create a function named speak . speak returns a function named logIt . And finally all logIt does is log the value of words to the console, in this case that means it logs 'hi' to the console.

Once you’ve got that copied into your console, we’re going to create a variable and assign it to our speak function as so:

var sayHello = speak();

Now we can see what the value of sayHello is by calling the variable but not invoking the inner function:

sayHello; // function logIt() {

// var words = 'hi';

// console.log(words);

// }

As expected, sayHello is referencing our returned inner function. This means that if we run sayHello() in the console, it will invoke and run the logIt() function:

sayHello();

// 'hi'

It works! But this isn’t anything special. Let’s move one line of code and see what changes. Take a look at the example below. We’ve moved our declaration of the variable words outside of the inner function and into the speak() function:

Like before, lets declare a variable and assign it to our speak function:

var sayHello = speak();

Now we’ll take a look at what our sayHello variable is referencing:

sayHello // function logIt() {

// console.log(words);

// }

Uh oh. There’s no words variable definition. So what’s going to happen when we invoke the function?

sayHello();

// 'hi'

It still works! And that’s because you’ve just experienced the effects of a closure!

Confused? That’s ok. Think back to our closure definition:

A closure is a function that has access to the parent scope, even after the scope has closed.

In this case our speak() function’s scope has closed. This means the var words = 'hi' should also be gone. However, in JavaScript we have this cool little concept called closures: Our inner function maintains a reference to the scope in which it was created. This allows the logIt() function to still access the words variable — even after speak() has closed.