Updated June 28, 2023
Introduction to JavaScript Closure
We have a tremendous and most frequently used function in a javascript programming language named closures. Using the closures, an inner function can access the variables and parameters of its outer function inside its body. This opens up many possibilities and benefits where this can be used. To understand closures, it is required to know the scope of the variables in javascript. Javascript closures only come into the picture when the functions are nestled.
A closure function can access three scope chains: its scope, the outer function’s scope, and the global variables’ scope. A closure function can access its variables and arguments defined in its closed curly braces {…}, the outer function’s variables and arguments, and the global variables declared.
Examples to Implement JavaScript Closure
Let us see how this can be implemented with the help of an example.
Example #1
Code:
<!DOCTYPE html>
<html>
<body>
<p>Demonstration of Javascript Closure</p>
<button type="button" onclick="testClosure()">Check Your Message</button>
<p id="sampleDemoOfClosure"></p>
<script>
function displayMessage (param1, param2) { var outerVariable = "Hi, ";
function prepareGreetings () {
return outerVariable + param1 + " " + param2;
}
return prepareGreetings ();
}
function testClosure() {
var message = displayMessage ("Good", "Morning"); document.getElementById("sampleDemoOfClosure").innerHTML = message;
}
</script>
</body>
</html>
Output:
The output is as follows after clicking the “Check Your Message” button,
In the above code, the prepareGreetings method can access the variable, namely outerVariable of method displayMessage, and parameters to displayMessage function, namely param1 and param2 in its scope. DisplayMessage is the outer method, and prepareGreetings is the inner method.
Example #2
Global variables can be defined outside all the functions using var, let, or const; however, any variable not defined using var, let, or const is global in javascript, which can be present inside or outside the function and is accessible throughout the window scope. Unlike the local variables, which have a lifespan of their function or block execution, the global variables have a lifespan until the page is discarded or the window is closed, or we navigate to some other page. Let us check this out with the help of an example. Here we will modify the above program, add a global string, and access it in the inner function.
Code:
<!DOCTYPE html>
<html>
<body>
<p>Demonstration of global variable in Javascript Closure</p>
<button type="button" onclick="testClosure()">Check Your Message</button>
<p id="sampleDemoOfClosure"></p>
<script>
var greeting="Have a great day ahead!"; function displayMessage (param1, param2) { var outerVariable = "Hi, ";
function prepareGreetings () {
return outerVariable + param1 + " " + param2+". "+greeting;
}
return prepareGreetings ();
}
function testClosure() {
var message = displayMessage ("Good", "Morning"); document.getElementById("sampleDemoOfClosure").innerHTML = message;
}
</script>
</body>
</html>
Output:
The output after clicking the buttons is as follows,
Example #3
Inner functions or closures in JavaScript retain access to their outer function’s scope chain even after the outer function has been returned.
Let us have a look at it with the help of an example.
Code:
<!DOCTYPE html>
<html>
<body>
<p>Demonstration of Javascript Closure after outer function is returned</p>
<button type="button" onclick="testClosure()">Get Today's Quote</button>
<p id="sampleDemoOfClosure"></p>
<script>
function getQuote (storiesStatement) {
var politicsStatement = "Politics always change.";
function prepareQuote (realityStatement) {
return politicsStatement + storiesStatement + " " + realityStatement;
}
return prepareQuote;
}
function testClosure() {
var todaysQuote = getQuote (" Stories"); var message = todaysQuote (" never do.");
document.getElementById("sampleDemoOfClosure").innerHTML = message;
}
</script>
</body>
</html>
Output:
The output after clicking the “Get Today’s Quote” button is,
As we can observe, the getQuote function acts as the outer function that returns the stored value (the inner function) collected in the todaysQuote variable. Execute the closure method “prepareQuote” using the collected variable “todaysQuote.” The method will return the quote that includes both the parameters and variables of the inner and outer functions.
Example #4
Closures do not store the values of outer variables; instead, it stores their references. You can change outer variables before calling the closure. This helps us to use the private variables in javascript.
We will see an example demonstrating the usage of private variables with the help of closures.
Code:
<!DOCTYPE html>
<html>
<body>
<p>Demonstration of using private variables with the help of javascript closures</p>
<button type="button" onclick="testClosure()">Get Employee Id</button>
<p id="sampleDemoOfClosure"></p>
<script>
function employeeId () { var employeeId = 1001;
return {
getEmployeeID: function () { alert("Employee Id is "+employeeId+".");
},
setEmployeeID: function (currentId) { employeeId = currentId;
}
}
}
function testClosure() {
var employeeNo1 = employeeId (); employeeNo1.getEmployeeID(); employeeNo1.setEmployeeID(1500); employeeNo1.getEmployeeID();
}
</script>
</body>
</html>
Output:
The output of the above code after clicking the “Get Employee Id” button gives two alerts, as shown,
The inner functions, namely getEmployeeID() and setEmployeeID() help to retrieve and assign the current value to the employee id field. Firstly, the employeeId is initialized with a 1001 value; hence, while retrieving the value, the first alert gives the message “Employee Id is 1001”.When inner method closure setEmployeeId is called with value 1500, the employeeId variable of outer function scope is changed, and hence the second alert returns the “Employee Id is 1500” message.
Closures Can Sometimes Lead to Bugs
As closures can access the updated values of the outer function at the position of their declaration, they can result in unexpected behavior, mainly when used for loops. These bugs occur because closures have access to the references of variables instead of their values. However, we can avoid such bug occurrences using Immediately Invoked Function Expression (IIFE). Using immediately invoked function expressions to pass only the value of the variables or parameter instead of its references solves the problem when using loops with closures.
Conclusion
This way, we can use javascript closures to achieve data hiding, abstraction, and private variables, leading to encapsulation. Javascript closures offer the advantage of providing extensive accessibility to outer function variables, making them applicable to a great extent. However, you must be careful while using them with loops, such as for loops, to avoid referential access and enable value access by using Immediately Invoked Function Expression along andres.
Recommended Articles
This is a guide to JavaScript Closure. Here we discuss the introduction, top examples of JavaScript Closure, and code implementation. You may also look at the following articles to learn more-