Can you explain what is a closure in JavaScript?
This is without a doubt one of the most popular questions in front-end interviews. There is a 99% chance you have faced this question in your JavaScript interviews round.
And it is justified.
The closure is such a non-trivial concept that you might have already used it without realising it.
We will see some real development scenarios that involve closures, but first, let us understand what closure actually is.
What are closures in JavaScript?
The entire concept of closures is based on scopes. And scopes decide where can we access a variable or function in our program. As simple as that. Scoping defines which parts of your code can access what. Take a look at the example below to understand scoping better.
// Variable a has access everywhere because
// it is defined globally.
var a = 10;
function print() {
console.log(a);
// Variable b has access inside this function because it is defined inside
// the function. If b is accessed outside function print, it will give an error.
var b = 20;
if (true) {
// Variable c has access inside this if block only because it
// is defined inside the block using let.
// If c is accessed outside the if block, it will give an error.
let c = 30;
console.log(a, b, c);
}
// This line will give an error as we are trying to
// access c outside its scope
console.log(c);
}
console.log(a);
print();
Now that we are clear on scopes, let us see how JavaScript handles scopes.
JavaScript follows lexical scoping. This means that, when accessing a variable, if it is not found in the current scope/block, JavaScript will check the parent scope.
And if still not found, JavaScript will check the parent's parent scope. This way, that variable is searched all the way up to the scope hierarchy. And if not found, JavaScript throws an error.
In the case of the previous code snippet, when we are accessing variable a
in the if block
, it is not present there. So JavaScript goes all the way up to the global scope and gets the value of a
.
Now we have enough ground to learn closures.
A closure is function bundled with its lexical scoping.
To put it in simple words, when a function is accessing variables from outside of its scope, the function and those variables form a closure.
Why do they form a closure? — Because, when that function is executed, even if the parent scope has finished executing, it will still need those variables. This typically happens when we are returning functions from functions.
Let us look at an example to understand this better.
function outerFunction() {
var outerVariable = 'I was in outer scope and now I am in closure with innerFunction';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const returnedFunction = outerFunction();
returnedFunction();
Let us dissect what is happening here:
-
outerVariable
is declared inouterFunction
's scope. -
innerFunction
usesouterVariable
and it is returned without executing. - When line number 11 is executed, scope for
outerFunction
is vanished. - But when we execute
returnedFunction
, it still prints value ofouterVariable
- So what happened is:
innerFunction
was returned with variables from the outer scope bundled together. So in other words, a Closure was returned.
THAT'S IT!! That is all you need to know about closures. Of course, there are some other complicated examples. It will be easier for us to understand those now.
One important caveat with closures is that closures hold references to variables from the parent scope. Not the values. So functions with closures can change values and get updated values. This will be useful in other real examples listed below.
Real-world applications of closures
As I mentioned earlier, you might have used closures without realizing it. Following are some use cases I have encountered where closure was a better solution.
- Writing your own debounce function
- Writing your own throttle function
- Implementing private variables
- Maintaining states
This article was originally published here. For more such interesting reads, visit my blog.
Top comments (0)