Making Sense Of JavaScript’s Closure With Some Examples

Closure is one of those things in JavaScript that you read a lot about but never fully get. Like with a lot of things in programming, you just need to play around with some examples to fully understand and appreciate the concept.

Instead of explaining to you what closure is, I’m going to show you some examples of how closure is used and walk you through the process of designing your application to take advantage of closure.

Here we go!

Photo by Riccardo Annandale on Unsplash

What is a Closure?

I like this definition from Secrets of the JavaScript:

A closure is a way to access and manipulate external variables from within a function.

I like to think of a closure as a feature of the programming language to let us do cool things such as:

Object Oriented Programming in JavaScript:

https://medium.com/media/2d84b42f727c4a4a1bacf01c60cb456c/href

and recursion:

https://medium.com/media/dabb631c3d117c23b4e7a8f3a401933e/href

Let’s try a couple of things based on the function we created in the recursion example:

https://medium.com/media/bff1d352d9b386d2ffaa3d0ccce96233/href

So far so good…

https://medium.com/media/fcbf1a5213f6433f6a8140efc6aced72/href

…Uh oh what happened?

Some Observations:

  • incrementUntil can call itself because it maintains a closured reference to itself. This makes recursion possible in JavaScript.
  • incrementUntil also maintains a closured reference to num and can read and modify it. The scope of num is window if you typed this example as-is directly into the browser console.
  • Although incrementUntil is being executed inside of myFun2, it didn’t modify the num in myFun2’s scope because incrementUntil only recognizes the num that was inside of its parent’s scope when it was first created (e.g., window). It doesn’t recognize the num inside of the caller, myFun2, because it doesn’t maintain a closured reference to its caller’s scope.

Here’s how we can fix myFun2 so it can leverage the incrementUntil function to modify the num inside of its own scope.

https://medium.com/media/0ac453aaccc5f64d53f6d6226055eaa1/href

The “fix” for myFun2 seems to work fine but it lends itself to a lot of duplicate code. What if we have to increment variables inside of other functions? It’s not good practice to copy-paste the same function/code into multiple places. Let’s refactor our incrementUntil function using partial application:

https://medium.com/media/24328584a9d3e2e0dd8630ac4214529d/href

The refactored incrementUntil function does not read or modify anything outside of its own scope so it’s a pure function, which illustrates a core principle of functional programming. You call the function as follows: incrementUntil(max)(num), which reads “increment until max starting from num”.

A really nice thing about partial application is that we can partially evaluate the final solution by providing our function a subset of the arguments it needs. Then we can save the intermediate solution to a variable so we can save ourselves some processing time by eliminating the need to evaluate the same intermediate solution every time we call the function to do similar things (assuming your programming language supports this kind of optimization).

Here’s what I mean by that in code:

https://medium.com/media/cf4337c0f35d54535667e50f84e68eb1/href

What’s happening in the code above is that you created a closure to keep the value passed to the function multThenAdd even after the inner function is returned. The inner function that is being returned is created within an outer function, making it a closure.

The above code is equivalent to the following in ES6:

var multThenAdd = num => mul => add => num * mul + add

Quite elegant but the syntax could seem really strange for someone coming from an imperative language background.

Now you’ve seen partial application in action, here’s a high level discussion on the concept of partial application (also called currying by some).

Partial application is basically a design pattern where your function returns another function that takes an argument. For example, you can call your function like this: myFun(arg1)(arg2), which is equivalent to:

const myFun2 = myFun(arg1)
myFun2(arg2)

Partial application is a powerful design pattern because you can continuing chaining things like myFun(arg1)(arg2)(arg3)… What’s happening here is akin to an assembly line in a factory: One argument at a time is applied to myFun to evaluate a better and better partial solution until all the arguments are applied to provide a complete solution.

Here’s an actual piece of code I wrote for a Node/Express app that uses the partial application pattern:

https://medium.com/media/6a9e59fde6b4052440cae22ecbc96690/href

I hope this helped some of you get a better handle on JavaScript and closure.

Thanks for reading! Here are some resources that that inspired me to create the content of this article:

Resources


Making Sense Of JavaScript’s Closure With Some Examples was originally published in DailyJS on Medium, where people are continuing the conversation by highlighting and responding to this story.

You may also like...