JavaScript closures are powerful feature rarely used by web developers. In fact, many of them often wonder what are JavaScript closures and how to use them. JavaScript closures help developers use variable scope in a powerful new way. However, it can be tricky to get past the initial learning curve. In this article, we will learn how JavaScript closures work.
What Are JavaScript Closures
First of all, let us understand the definition of JavaScript closures. A closure is a combination of a function along with its surrounding state information. In other words, it is a function that can access the scope of its parent function, even after the parent function has stopped execution.
How JavaScript Closures Work
Before we learn more about closures, it is essential to understand a little bit about scope, global variables and nested functions.
Scope
Scope is the boundary within which a variable is accessible. Generally, JavaScript variables have global or local scope. Global scope variables are accessible from any part of the JavaScript code. Local variables are accessible only within the function where they are defined.
var a = 1;
function b(){
console.log(a*2); //output is 2
}
b();
In the above example, the function b() is able to access the value of global variable.
A function can access all variables that are defined in it as well as all global variables defined outside the function. If a function is defined inside another function, then such a function is called nested function, and the outer function is called parent function. A nested function can also access variables defined in its parent function.
function out(){
var a=1;
function in(){
console.log(a*2); // output is 2
}
in();
}
out();
In the above code, nested function in() is able to access variable a defined in parent function out().
But a function cannot access variables that are defined in another function that is not a parent function. Similarly, a parent function cannot access variables defined in its nested function. The following code will not work properly.
function a(){
var c=1;
}
function b(){
console.log(c*2); //output is undefined
}
b();
Sounds confusing? Sadly, it is so. If we are not careful about variable scope, your variables may end up getting modified without your knowledge and you may find it difficult to debug this problem.
Suppose you want to create a simple counter function that keeps a count. And you want to make this accessible to all parts of your program. One of the simple ways is to use a global variable as shown below.
Global Variables
Here is the code to implement a counter() function using global variable.
var count=1
function counter(){
count+=1;
console.log(count);
}
Let us call the above function twice hoping that the counter variable will be incremented in each call.
counter(); // output is 2
counter(); // output is 3
The above code works fine but the problem is that any code on your page can modify the value of count variable. So it is not safe.
Instead, if you define it as local variable, then the count variable will be initialized in every call. This defeats our purpose.
function counter(){
var count=1;
count+=1;
console.log(count);
}
counter(); //output is 2
counter(); //output is 2
counter(); //output is 2
To protect your variables from being modified unnecessarily, you can try using nested functions as shown below.
Nested Functions
Here is an example of in() function nested inside out() function.
function out(){
var count=1;
function in(){
count+=1;
console.log(count);
}
in();
}
out();
In the above code, in() function is able to access and modify count variable defined in its parent function out(). But every time, we can run in() function only by calling out() function. Every time we call out() function, count variable is reset to 1. It would have been nice if we could call in() from outside out() function. This is where closures come in.
Closures
Here is a simple example of using closures with self-invoking function.
var add = (function () {
var count = 1;
return function () {count += 1; return count;}
})();
In the above code, the self-invoking function is run only once. It sets count to 1. Every time we call add() function, it will increment count variable.
add(); // count is 2
add(); // count is 3
add(); // count is 4
This provides two significant advantages. First of all, it protects count variable from external manipulation. Secondly, it preserves the value of count variable across multiple function calls.
When to Use JavaScript Closures
There are some interesting use cases for JavaScript closures
- Private variables – Closures allow you to protect your variables from being accessed or modified by another parts of your code. They allow you to correctly process the variable and only return the final value.
- State Persistence – In our example of counters, we have seen how the count() function retains the value of count variable, across different function calls. So they are useful for event driven programming which require state persistence.
- Modular code – Since closures define function scope, they allow web developers to build modular code blocks.
- Callbacks – Closures are also useful for callbacks and asynchronous programming.
Conclusion
In this article, we have learnt what are JavaScript Closures and how they work. You can use them as per your requirement. They are unique and serve their purpose very well. They might seem intimidating at first but once you get past the initial learning curve, you’ll see that they are very handy.
Also read:
How to Check Whether String Contains Substring in JavaScript
How to Remove Property from JavaScript Object
How to See Foreign Keys Related to Table in MySQL
Sreeram Sreenivasan is the Founder of Ubiq. He has helped many Fortune 500 companies in the areas of BI & software development.