JavaScript - Closures
JavaScript - Closures
What is Closure?
The concept ofclosuresin JavaScript allows nested functions to access variables defined in the scope of the parent function, even if the execution of the parent function is finished. In short, you can make global variables local or private using the closures.
A JavaScriptclosureis basically a combination of the function and itslexical environment. This allows an inner function to access the outer function scope. A closure is created every time a function is created at the function creation time.
Before you start learning the concept of closures, you need to know the concept of lexical scoping, nested functions, and returning functions.
Lexical Scoping
In JavaScript, the lexical scoping is a concept in which the scope of the variables is determined at the code compilation time based on the structure of the code. For example, the nested function can access the variables from the parent functionβs scope is called lexical scoping.
Nested Function
You can define the function inside the function, and the inner function is called the nested function. Letβs learn it via the example below.
Example
In the example below, we have defined the inner() function inside the outer() function. Also, the inner() function is executed inside the outer() function.
When we execute the outer() function, it also executes the inner() function, a nested function.
Output
The outer function is executed!
The inner function is executed!Returning Function
When any function returns the function instead of a value or variable, it is called the returning function. Letβs look at the example below.
Example
In the below code, the outer() function returns the function definition, and we store it in the βfuncβ variable. After that, we use the βfuncβ variable to invoke a function stored in that.
Output
The outer function is executed!
The inner function is executed!
The inner function is executed!Now, you learned the prerequisite required to learn the closures.
The definition of JavaScript closure is a bit confusing, but we will learn the closure concept step by step so it will be clear to you.
A Counter Dilemma
For example, you create the counter to increment and decrement the variable. As shown below, you need to use the global variable for the counter.
Example
In the example below, the βcntβ, a global variable is initialized with 100. Whenever the decrement() function is executed, it decreases the value of the βcntβ variable by 1.
Output
The value of the cnt is: 99
The value of the cnt is: 98
The value of the cnt is: 97The above code perfectly works as a decrement counter, but the problem is βcntβ variable can be accessed in the code anywhere, and any part of the code can change it without executing the decrement() function.
Here, JavaScript closure comes into the picture.
Example: JavaScript Closures
The counter() function returns the decrement() function in the example below. The βcntβ variable is defined inside the counter() function rather than in the global scope.
The decrement() function decreases the value of the βcntβ by 1 and prints in the output.
The βfuncβ variable contains the decrement() function expression. Whenever you execute the func(), it calls the decrement() function.
Output
The value of the cnt is: 99
The value of the cnt is: 98
The value of the cnt is: 97Now, letβs remember the definition of closure again. It says that the nested function can access the variables from the outer functionβs scope even if the execution of the outer function is finished.
Here, the execution of the counter() function is finished. Still, you can call the decrement() function and access the βcntβ variable with an updated value.
Letβs look at another example of closure.
Example
In the example below, the name() function returns the getFullName() function. The getFullName() function merges the string with the βnameβ variable, defined in the outer functionβs scope.
Output
The full name is John DoeBenefits of Closure
Followings are some benefits of the closures in JavaScript β
- Encapsulationβ The closure allows developers to hide or encapsulate the data. It makes data private and inaccessible from the global scope. So, you can expose only the required variables and functions and hide other internal details of the code.
- Preserving Stateβ The function remembers its lexical scope even if the execution of the outer function is completed. So, developers can maintain the state as we were maintaining the state of the counter in the above examples.
- Improved memory efficiencyβ The closure allows you to manage memory efficiently, as you can only retain access to the necessary variables and donβt need to define the variables globally.