Closure()

Morgan P Stanley
3 min readAug 7, 2020

Closures are an important part of fully understanding Javascript. Unfortunately, I feel as if most explanations are not friendly to new people. So I am going to try to explain closures in simpler terms — while understanding there is a tradeoff between complexity and technical accuracy. If you find this useful, I invite you to further study closures and their usefulness using such resources as Mozilla’s MDN Web Docs.

1 — Understanding Scope

Scope is the area the compiler looks in when deciding the value of a variable. Any basic understanding of Javascript should also come with an understanding of scope. If you don’t understand scope, then I suggest you learn more about it before moving on to more advanced concepts like closures. For those of you who need a slight refresher, remember there are two kinds of scopes;

local — variables declared within a function are locally scoped and can only be accessed from within that function.

global — variables declared outside of functions that can be accessed from anywhere in your program.

2 — The Return Statement

When studying closures my main frustration came from not focusing on what was being returned, so hopefully, this section will help a few of you.

function returnTwo() {
return 2;
}
const x = returnTwo()console.log(x)//output: 2

The above should surprise no one. the const x is assigned the return value of the returnTwo function, and the same goes for functions:

function returnTwo() {
return 2;
}
const x = returnTwoconsole.log(x)//output: function returnTwo() {
// return 2;
// }

Notice the slight difference: in the first piece of code, we assigned x the returned value of function returnTwo; in the second piece, we assigned x the function itself. Hopefully, you’ll see why this is important in a second.

3 —Variable Lifetime

If the previous two topics didn’t teach you anything new, then that’s probably good. They’re two foundational items of Javascript and some of the first things you should learn. Whether or not that’s the case, this step is probably the biggest stumbling block, and most discussion regarding its relationship to closures I find inadequate. So hopefully this will help you find that missing piece.

When a global variable is declared, it is deleted when you leave/close the app. When a local variable is declared, it is deleted upon completion of the function. How then do closures have access to a local variable? When an object is created, an environment for that object is also created, and this environment keeps track of any variables that this object has access to. And as long as we have access to an object, we also have access to its environment. Closures have access to their parent’s variables because that is part of their environment.

Now let’s look at a closure.

4 — Closures

function closure() {
let x = 0;
function addOne() {
return x += 1
}
return addOne;
}
const c = closure()
c() // x = 1
c() // x = 2
console.log(c()) // x = 3
//output: 3

Let’s go back over the previous three topics and see how they relate this our example.

Scope — The important function here is function addOne. It has access to variable x because it is declared within function closure.

Return — We assign c the return value of closure(). What is the return value of closure()? The addOne function. What is the value of c now?

console.log(c)
// output: function addOne() { return x += 1 }

Again, the addOne function.

Variable Lifetime — Now that we’ve assigned function addOne to c, the program will remember c’s environment — and that includes variables like x. So when we call c(), variable x is increased by 1, and then returned.

Hopefully, you now are at least starting to understand how closures work. I’ll end with the little reminder on often forgotten components of a closure:

When constructing a closure, we declare a variable outside the inner function, because if we declared it inside the inner function we would redeclare it every time we ran the function.

Then, we must return the function. If we don’t, then we’re assigning a variable (in my examples, c) to whatever our function did return — the default case being undefined.

Finally, if we want to be able to actually do anything with our ever-increasing variable, we should return that too. If we don’t, then, in the case of our example, x would increase by one each time we called c(), but we wouldn't be able to access it. :(

Good luck! 👍

--

--