Seriously though, WHAT ON EARTH is closure?!

Seriously though, WHAT ON EARTH is closure?!

Featured on Hashnode

Closure: it's not only what you need when a relationship ends, it's also something you need to understand when coding in JavaScript. Unfortunately, it can be a tough thing to explain to those new to programming, and since I only recently feel like closure has 'clicked' for me, I've decided to write a short article to explain it in ways other newer coders can understand. I hope this helps someone out there!

If you can write basic JavaScript functions, you have almost certainly already used closures without even realising it. In fact, for the longest time my main complaint about understanding 'closure' has been: "Isn't that just basic programming? Why do we even need a name for it?". Despite my protestations, I've been assured time and again that this is "a thing" and you need to know it, so let's stop dilly-dallying and get into it.

The basics of scope

Firstly, let's take a step back and think about the concept of lexical scope, which tells us which variables are accessible at any given time. Consider the following code:

function add (a,b) {
   let sum = a + b
   return sum
}
console.log(sum)

You probably already understand that the reason the above doesn't work is that we can't access sum because it exists only within "the world" of the function add. This "world" is known as scope, and it is created by our darling curly braces { and }.

Accessing scope from within and "local binding"

"Local binding" is just a fancy pants way of referring to variables declared within the scope of a function. In other words:

function funkyTown(){
   let localBinding = "this is a local binding"
}

Let's expand on this a bit: if we know that we can access local bindings anywhere within the "world" of a function, then we can add a line like this:

function funkyTown(){
   let localBinding = "this is a local binding"
   console.log(localBinding)
}

funkyTown()

Does the above function call log to the console? YES. We can access localBinding because we're still within the existing scope of our funkyTown function.

Wouldn't you know it, the above example also includes a closure! Our console.log is a function which references a local binding in an enclosing scope (whew!) and is therefore considered a closure.

"Closure" vs "A closure"

I'm going to just to a straight copy-paste from an excellent online resource, Eloquent JavaScript, which clarifies the situation in just a few words (emphasis mine):

"Being able to reference a specific instance of a local binding in an enclosing scope—is called closure. A function that references bindings from local scopes around it is called a closure." - Eloquent JavaScript Chapter 3

In other words, closure as a concept refers to the ability and idea of referring to variables which only exist within the "world" they were created: the scope created by curly brackets. Since we cannot access these variables from outside that scope, closure can only exist from within it. As I mentioned earlier: you have probably known that you can only access variables within their own scope for a long time, but now you know that the ability to do so is called closure.

To expand on this even more, a closure therefore refers to any instance in which you use the above ability in a function. Any function which references variables existing only in its enclosing scope, is itself a closure.

One more example for the road

Since this article is aimed at beginner-to-intermediate learners, I won't dive too deep into the ways in which we can use closure more complexly, I'll just pop another example of a fairly simple closure in here.

 // a function which will only divide even numbers
function divideEvens(num, divider) {                

   // local binding
   let isEven = (num % 2 === 0) ? true : false;   

   // a closure function
   function doDivision() {                

      // references to local bindings                     
      return (isEven) ? num / divider : null;           
   }

   // uses the inner function to refer to local bindings 
   return doDivision()                                          
}

console.log(divideEvens(24, 4))           
// logs 6

Of course the above is not the best way to implement the goal of the code, but simply acts as a verbose example.

Conclusion

As a programmer, you will frequently define and refer to variables from inside the scope of a function. As you do so, and as you use and reuse those variables in that "world", you are unknowingly utilising closure to your advantage. There is a difference between closure as a concept, and 'a closure' as a piece of code utilising that concept. Using closures is an everyday part of programming, and although knowing the name for it sometimes seems a bit odd, you can hopefully now see why they're important and give a relatively simple explanation of them if needed.