Closures are one of those concepts that a lot of new developers seem to have trouble with. Myself being one of them. In this post, I will attempt to make this mystery-shrouded concept a little less mysterious by addressing the point I initially missed when learning closures: persistence of data.
Here is the official definition of Closures according to MDN: "A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time."
Closures in JS have three main traits:
- A function must return another function
- The inner function has access to variables from the outer function
- Variable value from the outer function is persisted
Let's look at an example closure:
function parentFunc() {
var counter = 0;
function childFunc(){
let innerCounter = 0;
innerCounter++;
counter++;
console.log(counter, innerCounter);
}
return childFunc;
}
const myChild = parentFunc();
myChild();
In the snippet above, we have a function called parentFunc()
which returns it's nested function childFunc()
. parentFunc()
has a var counter
set to 0. childFunc()
has a var innerCounter
set to 0, it increments both counter
and innerCounter
, then logs both. We set const myChild
equal to the executed parentFunc()
.
The output is for the above code is:
1 1
Pretty straightforward, right?
What if we execute myChild()
more than once?
function parentFunc() {
var counter = 0;
function childFunc(){
let innerCounter = 0;
innerCounter++;
counter++;
console.log(counter, innerCounter);
}
return childFunc;
}
const myChild = parentFunc();
myChild();
myChild();
myChild();
The output is now:
1 1
2 1
3 1
In regular functions, once the function is executed it is wiped clean and does not persist any data.
When using closures, however, the inner function stores variables from the outer function in its own special location, which we can think of like a backpack. The outer function executes and data within it is wiped clean, but the inner function has that data stored in its backpack which it can reach into and grab. Note that it is only storing the variable from the parentFunc() in the backpack, it's own variable innerCounter
gets treated as a regular function and wiped clean after execution.
childFunc()
persists the value for var counter
as it is when the function completes. Meaning that at the start of the second execution var counter
is not set to 0, it is set to 1 and at the start of the third execution var counter
is set to 2.
This makes the use of closures a great option when we want to remember certain values in functions.
Conclusion
Closures in JS have three main traits:
- A function must return another function
- The inner function has access to variables from the outer function
- Variable value from the outer function is persisted
Closures are subtle concepts in JavaScript that can be difficult at first. But once you break them down and understand the three main traits, you may realize that they don't have to be so controversial.
Hopefully, this post helped you better understand the concept of closures in JavaScript!
Top comments (3)
What‘s the benefit of closures over classes?
Hope this helps you to understand which one is better: wiki.c2.com/?ClosuresAndObjectsAre...
Closures offer simplicity whereas classes have better performance.
I found this to be helpful as well: medium.com/engineering-livestream/...