Getting “Closure” on closures

Aaron Billings
7 min readJun 4, 2020

If you’ve been in the JavaScript community for any length of time you’ve probably heard people say things like “You’ll never understand JavaScript until you understand closures” or “ You can’t be called a real developer until you have a solid grasp of closures”. I didn’t really understand closures until I viewed JavaScript hard parts on Front-end Masters. Will Sentance gives a masterful lecture on closures. If you have doubts about closures take that course. You’ll thank me later.

We can sit and debate people who say this but one thing is true, you do need to understand closures if you really want to get the most out of JavaScript. What do I mean? Well, let me illustrate.

Suppose you bought a brand new muscle car. You were super excited to get it and you’ve been driving it around town a lot. You can get from point A to point B and then all the way to point C. It’s a great car! However, there are features of your car that you probably don’t even know yet, features that once you understand will not only allow you to get the best performance out of your car but to have a deeper appreciation for the car and it’s makers.

The same goes for JavaScript. You can certainly develop applications without having a strong grasp of closures. However, once you do understand it you now have a way to get more performance out of JavaScript code than before. This means you can build more robust applications. This is the basis for Currying, factory functions, IIFE’s (Immediately Invoked Function Expression) and the module pattern, and more cool stuff in JavaScript. Who wouldn’t want to do all of that?

What is an Execution context?

Before we dive into closures we need to understand something called the execution context.

There are three types of execution contexts. Global and function and eval (eval isn’t covered here).

Global Execution Context

This is the place where all of your code is executed for the first time. However it’s a bit more than that. It’s really anything in the flow of execution (JavaScript runs from top to bottom) that isn’t inside of a function and all is it’s variable environment or state. So as your code runs it starts saving variables and function declarations to memory. As the name suggests there can only be one Global Execution Context.

Function Execution Context

As the flow of execution continues in Global it may encounter a function call. Once it sees that it creates a new Function Execution Context. Each function execution context creates its own local memory (variable environment or state). However, once a function has finished running and returns an output the local memory (state or variables) gets deleted, so functions have no permanent memory by default.

If you want even more info on this look at this article here

However, what if we could give our functions a memory? What if we could allow them to carry a permanent local memory (state) with them and have it with them for the life?

What is a Closure?

So…. what is a closure? Many will tell you it’s the stuff in side the curly braces of a function. But does that really explain what it is? Not really. To get a good understanding let’s take a look at some code.

What’s happening here?

We have a function named outer. This function contains a variable named counter with the value of 0. Next we have a function declaration named incrementCounter which increases the counter variable. We are then returning the function incrementCounter. Then we are declaring a constant with the name “myNewFn” and giving it the returned value of our outer function.

So, what’s so special about this. Let’s see what happens when we call “myNewFn()”. Copy the code and run it in a browser and see what happens. I’ll wait…..

When you run it, you get “1”. Now, you may say “wait a sec… counter is inside the outer function not inside of incrementCounter function, how does it still run.” This is probably one of best things about JavaScript.

You see, JavaScript is a lexical or statically scoped language. This means that where the function is depends on what data it will have access to for the life of the function. Basically, when we created “incrementCounter” and returned the function, it looked at the surrounding state that it was using and took it, namely the counter variable. Now the function incrementCounter has its own permanent counter variable set at zero and can use it anytime we call it. Pretty cool right?!?!

To illustrate, imagine for a moment that whatever house you were born in you got to keep certain things in the house for the rest of your life. No matter where you go until you die those certain belongings from that house are yours and you can use them anytime you like wherever you like. This is in essence what a closure is.

However, closure isn’t a great name for this is it? That’s because it doesn’t describe what its actually doing. As Will Sentance put it, it’s a “backpack” on the function with all of the data from where it was created. So as soon as the incrementCounter function is created JavaScript sees that the function is using the counter function and before it’s returned out to the Global scope, stuffs it in the backpack and gives it to the function to have forever and ever. It can’t be taken away but also it can’t be directly altered except by calling the function.

There’s also another name for this, a P.L.S.R.D or Permanent Lexical Scoped Referenced Data. But that’s a mouthful, I like backpack much better.

Now let’s change things up a bit. What if we create a new constant named secondFn and gave it the return value after the function outer has run. Then we call secondFn twice. What does it evaluate out to be? Go ahead and take the code and run it right quick.

const secondFn = outer()secondFn()secondFn()

If you got “1” then “2”, you are correct. But why? Well, that’s the beauty of the backpack. Every time you call function outer and stuff it in a new constant it takes with it a brand new backpack with a totally separate counter variable which is set to zero.

What if we put the counter variable inside the IncrementCounter function and run it. All of them would evaluate to 1.

Now, let’s move the counter variable outside both functions to the global state. Now it’s 1 2 3.

Why does this happen? Since the variable is in the global scope all the functions pull from the same variable and iterates the counter.

Practical Uses

Now that we have a better understanding of what closures are, let’s talk about some of the fun things we can do with them. As stated in the beginning of this article, closures are the basis for many of the features of what we know as modern JavaScript. Since this examples are a little more complex for this article let’s dive into a more simpler use case using the new knowledge about closures we have learned.

What if we wanted to create a function that could only be executed once and when it’s run again it would just return the same first result each time. This could be useful in situations where a feature in an application should only be used one time by the user and subsequent calls should return the same value. Let’s see how we could implement that using closures.

Let’s break this function down. First, we are creating a function called once that takes a function as a parameter. This function has a variable called “result” which is uninitialized. Next we are returning a function that will take a number as a number as a parameter. Then we are calling the function with the parameter and storing the results in our variable result. We need make our function parameter equal to null so it can’t be called again. Finally we return the result.

The interesting thing about this function is that when it’s returned out it grabs the result and stores it in its backpack even though it hasn’t been assigned yet. Because it has access to that result variable it knows when the function has been called and will not let it be called again.

Let’s try the function out with an function that adds two to a number. Copy and paste the code in a browser and see if you get the expected results.

Pretty cool huh? This function is also an example of currying but that’s a topic for another article. Feel free to play around with this function and make it your own.

Closing thoughts

So to recap a closure is a backpack full of permanent data that the function takes with itself when it’s created and returned from another function. It can then use this data as many times as it needs and whenever and wherever it is called for the life of the function.

Closures give our functions persistent memories.

Hopefully, this gives you a clearer understanding of closures and their benefits. JavaScript is an interesting language with pretty cool features, when we take the time to go in depth we can better use our tool to it’s full Potential.

If you enjoyed this article please give it a like. Also, feel free to check out my other articles here.

--

--

Aaron Billings

Full Stack developer that follows the ABCs (Always Be Coding). If I’m not coding you can find me playing video games, or spending time with family.