Learn what closure is in JavaScript and how to use it to create reusable functions. Closures are a powerful feature of JavaScript that can help you write more concise and efficient code.
Closures in JavaScript are one of those concepts that many struggle to get their heads around. In the following article, I will explain in clear terms what a closure is, and I’ll drive the point home using simple code examples.
Before getting deep into the JavaScript closure, let us discuss little about lexical scope,
JavaScript follows Lexical scope, that means functions create their scope when they are defined and not when they are executed. Here, scope is nothing but the extent to which a variable can be accessed, if the extent to which variable can be accessed is only within function it is called local scope and if the variable can be accessed anywhere in program it is called **global scope. The Lexical scope says that, the functions don’t share local scope **i.e, variable defined in one function is not accessible in another function.
The following example illustrates the JavaScript Lexical Scope,
In the above JavaScript code , we are trying to display addition of two numbers. In this code, the add() function is called in numbers() function and we may think that since add() function is called in numbers(), the add() also has access to variables like a,firstNum and secondNum , but it is false because JavaScript follows lexical Scope i.e, scope creation depends on where the function is defined and not on where the function is executed/called. That’s why the add() has no access on variables of numbers() (even though add() is called inside numbers()) since it is defined outside of numbers(). **The output of this program will be firstNum is not defined. **Since JavaScript translates line by line, it encountered error at line 7 that is firstNum is not defined and displays it.
To overcome this problem which raised due to lexical scope , **CLOSURES came into existence. CLOSURES **are nothing but a function which can access variables of other function in addition to its variables and global variables. In JavaScript, this kind of feature is supported only by private/Inner function So, Closures are nothing but inner functions. One can create closure by adding a function inside another function.
The above problem is solved by closures as follows,
In this case, add() is defined inside numbers() and has access to all variables. The output will be : The result is 7.
There are 4 points with respect to closure,
To understand JavaScript Closures, one must first understand how JavaScript’s execution context differs from those of other languages.
In most programming languages, when a function is called, its execution context(that is the environment containing all the variables used by that function) is stacked on top of the context of the function that calls it. Something like this:
Here Global context is the environment of the global entity. In C programming, this would be the ‘main’ function. In JavaScript it would be the Window object. ‘one’ is a function called from within the Global context. ‘two’ is a function called from within the context of ‘one’. ‘three’ is a function called from within the context of ‘two’. They are all placed on top of each other and hence **isolated **from each other.
Any local variables you declare within any of the contexts above, is isolated from all other contexts. Only a global variable is accessible within all contexts.
But with JavaScript the call stack works differently.
In JavaScript, when a function is called, its context is placed inside of the context, that it is called from. Something like a box – within – a – box:
Sorry, for the totally unrelated graphic ;), but I hope you get the idea. Each box represents a context. The largest box represents the Global context. The smaller box represents the context of a function called from within the Global context. The smallest box represents the context of a function called from within the context of the smaller box.
Now imagine these boxes being fully closed. You see that the smaller boxes have access to the contexts within which they were called from(larger boxes). But the calling functions(larger boxes) don’t have access to the contexts of the functions(smaller boxes) they call. This behaviour is called closure.
This is the reason the behaviour is called ‘Closure.’. The calling contexts (larger boxes)close over the called contexts (smaller boxes).
Now lets see an example:
<script>
var e = 5; // Global Variable due to Global Execution Context (Closure)
function outer(){
var a = 1; //Local Variable
b = 3; // Global Variable by definition
function print(){
c = 2; // Global Variable by definition
var d = 4; // Local Variable
function printInner(){
console.log(a); //Outputs Local Variable ‘a’ due to Closure – ‘1’
console.log(b); // Outputs Global Variable ‘b’ – ‘3’
console.log(c); // Outputs Global Variable ‘c’ – ‘2’
console.log(d); // Outputs Local Variable ‘d’ due to Closure – ‘4’
console.log(e); // Outputs Global Variable ‘e’ – ‘5’ (Closure)
}
printInner();
}
print();
}
outer();
</script>
Now answer the following question:
If you included the variable ‘e’ in your answer, you’re wrong. It is a global variable.
‘e’ is not a global variable by definition. It is a global variable by Execution Context. Its execution context is the Window object, which closes over the execution contexts of any function called from within it. Hence it is accessible to any function called from within the Window object. This is an example of Closure.
Similarly the variables a and d while being local variables are also accessible within the function printInner. This is also due to Closure.
The reason for this difference in behaviour of the JS execution context, could be that it was primarily designed for DOM manipulation. A DOM has a tree – like structure with nodes as its branches.
Any change in the** state** of a node might affect the change in the state of its parents. Perhaps the designers of JS wanted to capture this behaviour in the language and that is why they made child objects(remember functions are first-class objects in JS) have access to the state(execution context) of its parent objects.
#javascript