Closure is one of the most notorious topic in JavaScript to understand. It holds a very high significance in the language and the way we write JavaScript on a daily basis. This also happens to be a common question in the interviews. There are tons of ways we can use closures. In fact, we might never even realize that we're using a closure. That's what makes it captivating.
Prerequisite-
- Execution context and scope
- Functions
Let's get started!
What is a Closure?
In general terms, a closure is formed when we have functions enclosed together. The inner functions will have access to the scope of the outer functions in which it is enclosed. A closure is created every time we create a function. Let's understand this with an example
function country(countryName){
return function(cityName){
console.log(cityName + " is located in " + countryName)
}
}
const globe = country("England");
globe("London")
//Output
"London is located in England"
In the above example, We see two functions bundled together. The inner function is using the parameter that belongs to the outer function. When we invoke the function const globe = world("England");
we get the entire inner function pointing to the globe
variable.
Surprisingly when we invoke globe("London")
, we still have access to the parameter that belongs to the outer function country. What exactly are we seeing here?
The reveal
When we created a function inside our country
function, a closure was formed. This gives us access to the variable that belongs to the outer function. Think of it as if the inner function and the outer variable are enclosed together inside a box during this process.
const globe = country("England")
, We return this entire box that includes the inner function as a whole along with the reference to the outer variable countryName
that was made available to use.
Let's see some simple examples of closures for a better understanding
Closures in a factory function
A factory function is a function that will simply act as a parent for the inner function.
function math(operation){
return function(number1,number2){
if(actionType === "addition"){
return number1 + number2
}
if(actionType === "substraction"){
return number1 - number2
}
}
}
const doAddition = math("addition");
const doSubstraction = math("substraction");
doAddition(2,2);
doSubstraction(4,2)
In the above example, We use a similar technique where the inner function will receive two parameters. We accept the operation we want to perform in the outer function. Our inner function targets the outer scope to check what kind of math operation we want to perform since we are using operation
inside the inner function.
When we call math("addition")
we return the inner function with the reference to the operation
variable because it has formed a closure i.e we have "addition" and the inner function in the box.
Closure with a callback
function notifyMe() {
var notification = "Hello";
setTimeout(function() {
console.log(notification);
}, 3000)
}
notifyMe();
This is rather an interesting example. There's a setTimeout
with a callback function which will be executed after 3 seconds once our notifyMe
function is invoked.
The End
Thank you very much for reading. I hope this was helpful in some way to digest closures. This is my second blog and I'm still learning, I'm open to any kind of feedback. Cheers!