Follow Me on Twitter @AnnaJMcDougall
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.
Top comments (1)
Your explanations are well put. Great read! Quick note on formatting. if you place a "js" right after the first set of backticks, DEV will highlight your syntax accordingly 🙂. So it would look like so if you replaced the single quotes with backticks:
'''js
// your code here
'''
Lastly, whereas your last example showcases the idea of closures, it doesn't quite reflect the benefit of them. A great example of a closure utilizing a lexically scoped variable would be a persistent counter without a global
count
variable. We know that whenever a function runs, it rebuilds any variable that is declared inside of it, rendering those variables non-persistent if we need to call that function multiple times. And if we don't want to pollute our global scope, we wouldn't want to declare the variable outside of any function. We'd need a closure to handle counting said variable! Example:When you think of closure's this way, you begin to see how powerful closures are. You're essentially creating a manageable state without the need to expose any variables globally! 🤯
I'm excited to read more of your posts and welcome to the Dev Community! ✌