Introduction
You must have worked with Javascript functions and closure is an essential concept of functions in javascript. So, in this blog, we will understand the concept of Closures in javascript and how it works.
Firstly we will understand the concept of lexical scoping.
Lexical Scoping
Lexical scope is the ability of a function to access variables outside its scope i.e. from the parent scope. Let us understand it with the help of an example:
let value = 'test';
function test(){
let name = 'John';
console.log("Value: ", value);
console.log("Name: ",name);
}
test();
Here value is a global variable and will be accessible in every function whereas the variable name is a local variable and will be accessible only within the test function.
If you try to access the name variable outside of the test function you will get an error message -ReferenceError: name is not defined
Closures
The concept of closures is related to scopes of variables. We have different lexical environments for every function. Each function creates its own environment for its variables. The closure is the concept where you can access an outer function’s scope from an inner function. Whenever a function a created, a closure for that function is also created.
Here is an example to better understand it:
Example of Closures
function myFunc() {
const name = 'John';
function displayName() {
console.log(name);
}
return displayName;
}
const test = myFunc();
test();
Here myFunc is the outer function and displayName is the inner function. When you run this you will get the output as ‘John’. But here we are returning the inner function even before executing it.
As we know that closure is the combination of a function and its lexical environment within which it was declared. So here the test variable has the reference to the function displayName which was created when myFunc was called. And the instance of displayName maintains its lexical environment which is why we have the name variable accessible.
function getNameAndDesignation(name) {
return function(designation){
return name + ' - ' + designation;
}
}
let employee1 = getNameAndDesignation('Tom');
let employee2 = getNameAndDesignation('James');
console.log(employee1('Software Engineer'));
console.log(employee2('Software Engineer'));
Here we have a function getNameAndDesignation that takes the name as an argument which in turn returns a new function. Another function takes designation as an argument and returns the name concatenated with the designation.
Here employee1 and employee2 are both closures which will have their own lexical environment.
So basically closure is created when the inner function keeps the environment of the outer function scope when the outer function has already been executed. When you run this file you will get the output as:
Tom - Software Engineer
James - Software Engineer
Performance
As we already know, each function maintains its scope and closure but we should not create functions within functions unnecessarily. The reason for this is that it will affect the performance in terms of speed and memory consumption. So until and unless you need to create a function within a function for a particular task, avoid nesting functions.
Also, keep in mind that variables declared within a closure are not garbage collected.
Conclusion
After understanding the concept of lexical scoping in Javascript, we went through the concept of closures in javascript. We looked at examples of closures and saw how functions are bundled together having references to their surrounding state which we call the lexical environment.
Closures are an important concept to understand. And we should not overuse it which will negatively affect your application. You may go through more details on closures in the official documentation here.
For more updates on such topics, please follow our LinkedIn page- FrontEnd Studio.