Have you heard of the many scoping options available in programming languages? Uhmm! I believe you are familiar with the terms global scope, local scope, and block scope. But, what do you think? The other form of scoping in javascript is where a variable’s scope is the location where it was defined rather than the place where it was executed.
The area where the variables are declared or the variable’s birthplace is known as the lexical scope. The variable’s lexical scope is the global scope if it is defined in a global area, and the function scope is defined in a function area.
The variable’s lexical scope referred to the variable’s origin rather than the place where it was raised. That is the defined area of the variable, not the called area.
The alternate name for lexical scope is static scope. Variables are often addressed during compile-time instead of runtime in lexical scoping.
In lexical scoping, the outer function variable can be used by the inner function even after the completion of the outer function’s execution. In general, a few programming languages’ working scenarios are that when an outer function execution is done, then the variables declared in the outer function are deceased and can’t be accessed in the inner function.
But in JavaScript, the outer function’s variables can be accessed even in the inner function, and the variables in the outer function will be alive if the use of the outer function variables exists in the inner function. This type of functionality in Javascript is called CLOSURES.
Let’s understand better by an example.
function myFunction(){
let name = 'Vinod Kumar';
function displayName(){
console.log(name)
}
displayName();
}
myFunction();
The above example is the model of lexical scope where the inner function displayName() can access the variable of outer function myFunction().
function myFunction(){
let name = 'Vinod Kumar';
function displayName(){
console.log(name)
}
return displayName;
}
let getName = myFunction();
getName();
If you carefully observe the above mentioned two examples, then you might find that the second example uses the return to access the variables of the outer function in the inner function.
We set the value given by the myFunction() method to the getName variable outside of the myFunction() function, which is a reference to the displayName() function.
Then, using the function’s reference: getName, we ran the displayName function(). We obtain the same result as the lexical scope example, which is quite intriguing in JS. This is due to the outer function variable value being stored, which is then used by the inner function. This notation is known as “CLOSURE.”
The worth noting point here is that a local variable is generally only present during the function’s execution and it is no longer available for further accessing. That is, from the example, the name variable is no longer usable after the myFunction() function has finished its execution. But here in this context, the name is still available for the inner function displayName.
[Also Read, Hoisting Variables and Functions in JavaScript]
Closure: what is it?
You have created a closure every time you define a function within another function. And the inner function is said to be a closure. The closures are usually returned so that the variables of the outer function can be used later. The inner function variables, local variables (outer function variables), and global variables can all be accessed through a closure.
When a function is generated in JavaScript, closures are formed throughout the function creation process.
How does closure work in JS? And what are the benefits of closures?
- When the outer function is called numerous times by the inner functions, the local variables of the outer function that are controlled by the inner function are unaffected even if there exist multiple scopes as of the inner function call.
- The outer function’s local variables controlled by the inner function will change as many times as the inner function is called if the outer function returns the inner function. That is, the resultant variable value of the inner function that is been accessed from the outer function variable will affect as many times as the inner function called, and the main local variable is still unaffected.
function calc(){
var x = 0;
function increment(){
return x++;
}
return increment;
}
const f1 = calc();
console.log(f1()); // 0
console.log(f1()); // 1
console.log(f1()); // 2
const f2 = calc();
console.log(f2()); // 0
console.log(f2()); // 1
console.log(f2()); // 2
Look at the example which clearly presents how the real value of the local variable ‘x’ is unaffected every time the inner function access it. And when the inner function is called numerous times under the same function call, it gets increased by one value of pre-existing value, that is why, we get 0, 1, 2… it gets incremented until the function call of the inner function ceases.
- Closures help in securing data, that is it has a data encapsulation operation.
- Redundancy can be cleared in closures.
- Variables always are tied to an execution context using closures.
- Closures are used for callbacks. A callback frequently refers to a variable defined outside of itself.
- Closures can be used for storing data which are returned from the functions.
- Closures are used to build private methods in which a class stores a private state while displaying public getter as well as setter methods.
function myFunction(role){
let _role = role;
function SetRole(newRole){
_role = newRole
}
return {
SetRole: function(newRole) {
SetRole(newRole)
},
getRole: function () {
return _role
}
}
}
const emp = myFunction('Junior web developer');
console.log(emp.getRole()) // Junior web developer
emp.SetRole('Senior web developer');
console.log(emp.getRole()) // Senior web developer
The SetRole function is not accessed by users and can access the private state variable by using a closure.
- Closures are also used in event handlers.
How do you know whether there exists a closure or not? And how do identify how many closures are created in function?
- When a function has nested functions, then understand that the inner function is a closure that stores the variables of the outer function.
- Closures are formed every time a function is created in JavaScript, during function creation time.
- The outer function must include local variables, and the nested inner function must use the outer function’s variable. This is what the closure definition means right?! Use the local variables even after the outer function execution is completed.
- The outer function must utilise return to return the inner function to the outer.
It is necessary to utilise the return in order to return the inner function. You can’t use the closure if you don’t return the inner function. Returning the nested inner function has the ultimate goal of allowing external access to the closure. So this way a closure can establish a liable communication path between inner and outer functions.
[Also Read, JavaScript Coding Interview Questions and Answers]
Wrapping up the concept of closures in javascript
- A closure is created every time you create nested functions. The inner function is generally called closures.
- The local variable is still accessed by the inner function even after the completion of execution of the outer function, and this has happened through the creation of closures which stores local variable data for inner function use.
- At a time numerous closures are created in a function based upon the inner function use of the outer function variables.
- A closure can access the inner function variables, local variables (outer function variables), and also global variables.
- Closures are formed every time a function is created in JavaScript, during function creation time.
- Closures are used for various purposes like data privacy, building private methods, event handlers, reducing redundancy of code, storing return data of the function, etc.
- When we use closures, the local variable is unaffected even if it is called numerous times by the inner functions.