If you’re new to JavaScript, or you’re prevailing JavaScript user mounting your knowledge and skills in the web designing, learning the basics of JavaScript is a well-intentioned job. But the best way to gain essential skills is by joining JavaScript classes in Delhi where you will implement the logics in real world examples.
Through professional JavaScript classes you can attain the required knowledge in the arena of web designing and development. Functions, variables, loops, literals etc. are some important topics which consist of huge complexions. One such topic is closure which we are going to comprehend today in this blog.
What is a Closure in JavaScript?
A closure is an inner function that is defined within outer function’s and inner function has access to both its own and outer function local variables and global variables. The outer function’s parameters can also be accessed by the inner function. You create a closure by adding a function inside another function. These functions can be named or unidentified function.
A global variable can be access by any script on the page and local variable is only accessible to the function where its defined.
Closure Example 1:
Let’s create a simple counter which increment on every button click.
First create a button and p tag with “btn” and “paraId” id respectively in HTML.
<p id="paraId">Output: </p> <button id="btn">Click</button> <script type="text/javascript"> var count = 0; function counter(){ count++; paraId.innerHTML = count; } btn.onclick = counter; </script> //output 1 //output 2 //output 3
Problem: Above code works fine but creating a global ‘count’ variable is not a good decision. The problem here is it can be accessed and changed by any script on page which we do not want as global variables are very useful but dangerous.
To avoid accidental change of global variable, we can declare ‘count’ variable inside the function.
function counter() { var count = 0; count++; paraId.innerHTML = count; } btn.onclick = counter; //output 1 //output 1 //output 1
But the code will not work and the output will always be 1 because the ‘count’ variable gets reset after every click.
Solution: A nested function can partly solve the issue, as inner function has access to all the variables and parameters above them. But to access inner function and to keep the ‘count’ variable initialized as 0 on every click, we need closure.
function myFunc() { var count = 0; return function () { count++; paraId.innerHTML = count; } }; var counter = myFunc(); btn.onclick = counter; //output 1 //output 2 //output 3
Explanation: Here myFunc() is assigned to counter variable which will invoke myFunc (outer function) and inner function will also be available. Within outer function the count variable will get initialized once and is set to ‘0’ and the count is now a private variable.
Now, every time user clicks the button already available inner function will get invoked and will return the counter with increment without executing the outer function and count variable again and again.
We can also code it with IIFE- Immediate Invoked Function Expression as below:
var counter = (function (){ var count = 0; return function (){ count++; paraId.innerHTML = count; } })(); btn.onclick = counter; //output 1 //output 2 //output 3
Example Explanation: The benefit here is that we do not have to call the function, it will be available as the script runs. To explain further an IIFE is self or immediately invoked function where we do not have to call the function it gets immediately executed when script runs. In above example the anonymous function runs automatically and it gets assigned to the variable counter.
Closure Example 2:
Create Interactive Text Size Change Utility on Click
Let’s add buttons to a page that adjust text size. For CSS – we will define the size of page in body (default will be 12px) and set the size in each header (h1, h2). After that for HTML create 3 link elements with id and text 12, 14, 16.
<head> <style type="text/css"> body {font-family: Helvetica, Arial, sans-serif; font-size: 12px;} h1 { font-size: 1.5em;} h2 { font-size: 1.2em;} </style> </head> <body> <h1>Heading</h1> <h2>Sub Heading</h2> <p>size12, size14, and size16 are now functions which will resize the body text to 12, 14, and 16 pixels, respectively. We can attach them to buttons (in this case links) as follows:</p> <a href="#" id="size-12">12</a> <a href="#" id="size-14">14</a> <a href="#" id="size-16">16</a> <script type="text/javascript"> function makeSizer(size) { return function (){ document.body.style.fontSize = size + 'px'; } }; var size12 = makeSizer(12); var size14 = makeSizer(14); var size16 = makeSizer(16); document.getElementById('size-12').onclick = size12; document.getElementById('size-14').onclick = size14; document.getElementById('size-16').onclick = size16; </script> </body>
Explanation: Here variable size12, size14, size16 now function, calls the outer function makeSizer with parameter, in makerSizer the available inner function takes the parameter and returns the body size of document.
Note: It saves you from creating 3 anonymous functions for all 3 buttons as you cannot directly assign a function with parameters value with onclick event in JavaScript.
Closure Example 3:
Emulating private methods with closures
In JavaScript we emulate the private method with the help of closure which means we keep the certain method private and out of the approach of user. This is very beneficial when making an API or when we want to restrict access to certain code which is data hiding or encapsulation as jQuery also does.
In the below example; we will see how to use closures to define public functions that can access private functions and variables also known as revealing module design pattern.
var counter = (function () { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function () { changeBy(1); }, decrement: function () { changeBy(-1); }, value: function () { return privateCounter; } }; })(); console.log(counter.value()); // logs 0 counter.increment(); //1 counter.increment(); //2 console.log(counter.value()); // logs 2 counter.decrement(); //1 console.log(counter.value()); // logs 1
Explanation: In above example there is one anonymous self-invoking function which will execute when the script run as in the earlier example. There are three public function increment, decrement and value which will help in accessing private attributes of counter and they are private function changeBy and private variable privateCounter. These private items cannot be accessed by anonymous function directly they can be access via public function only.
Creating multiple use of same function
Here we can store the function to a variable makeCounter and remove the IIFE and using it to create and call many times, as in below example counter1 and counter2
var makeCounter = function () { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function () { changeBy(1); }, decrement: function () { changeBy(-1); }, value: function () { return privateCounter; } } }; var counter1 = makeCounter(); alert(counter1.value()); /* Alerts 0 */ counter1.increment(); counter1.increment(); alert(counter1.value()); /* Alerts 2 */ counter1.decrement(); alert(counter1.value()); /* Alerts 1 */ var counter2 = makeCounter(); alert(counter2.value()); /* Alerts 0 */
Explanation: In this case both the counter1 and counter2 are separate and can be used independently. If counter1 is called the privateCounter gets updated for it only, it does not get update or change for other counter2. They both work independently and private variable or function does not change the value of one closure to other.
Closure Example 4:
Creating closures in loops: A common mistake
We want to create 3 input fields and associated onfocus help message.
Create 3 input fields – email, name, and age; each filed has an id which is looped to get the message as the user move the mouse to type.
<p id="help">Helpful notes will appear here</p> <p>E-mail: <input type="text" id="email" name="email"></p> <p>Name: <input type="text" id="name" name="name"></p> <p>Age: <input type="text" id="age" name="age"></p> <script type="text/javascript"> function showHelp(help) { document.getElementById('help').innerHTML = help; } function setupHelp() { var helpText = [ {'id': 'email', 'help': 'Your e-mail address'}, {'id': 'name', 'help': 'Your full name'}, {'id': 'age', 'help': 'Your age (you must be over 16)'} ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = function() { showHelp(item.help); } } } setupHelp(); </script>
Explanation: In above case we are not able to get the correct message, whichever field we click the message remains same “Your age (you must be over 16)”.
This is because the closure created using onfocus event is within the loop and the last value is always available to the output.
I am sure you will be eagerly waiting for the solution and closure is the rescue here.
function showHelp(help) { document.getElementById('help').innerHTML = help; } function makeHelpCallback(help) { return function () { showHelp(help); } } function setupHelp() { var helpText = [ { 'id': 'email', 'help': 'Your e-mail address' }, { 'id': 'name', 'help': 'Your full name' }, { 'id': 'age', 'help': 'Your age (you must be over 16)' } ]; for (var i = 0; i < helpText.length; i++) { var item = helpText[i]; document.getElementById(item.id).onfocus = makeHelpCallback(item.help); } } setupHelp();
To solve this, we need one more closure where makeHelpCallback function is created and every call for function points to the helpText array and the output is printed which is available in that function.
Closure Example 5:
Here, I am showing you that there are various ways to use function and function closure. A small change in you’re the parenthesis placement of function doesn’t affect output but change the way of coding.
Method 1- Using named function to return from the function without IIFE
function addnum(num1, num2) { var resultText = "Result is: "; // Here "add" inner function has access to the outer function' variables & parameters function add() { return resultText + (num1 + num2); } return add(); } var result = addnum(10, 10); function myFunction() { document.getElementById("demo").innerHTML = result; } Output: Result is: 20
Method 2- Calling inner function without parenthesis
function addnum(num1, num2) { var resultText = "Result is: "; function add() { return resultText + (num1 + num2); } //OR - if we remove the parentheses of inner function add, it will return the inner function expression without executing it. like this :- function add(){ return resultText + (num1+num2); } return add; } //here we create newAdd which will contain add() function (inner function) expression. var newAdd = addnum(10, 10); // call the newAdd function and store the return value in result variable var result = newAdd(); function myFunction() { document.getElementById("demo").innerHTML = result; } Output: Result is: 20
Method 3- Using double parenthesis to invoke inner and outer function
function addnum(num1, num2) { var resultText = "Result is: " function add() { return resultText + (num1 + num2); } //OR - if we remove the parentheses of inner function add, it will return the inner function expression without executing it. like this :- function add(){ return resultText + (num1+num2); } return add; } // This returns add() function (inner function) definition and executes it. Notice the additonal parentheses. var result = addnum(10, 30)(); function myFunction() { document.getElementById("demo").innerHTML = result; } Output: Result is: 20
Method 4 – Using IIFE or self-invoking function method
var addnum = (function () { var resultText = "Result is: "; return function () { return resultText + (10 + 20); } })(10, 30); var result = addnum(); function myFunction() { document.getElementById("demo").innerHTML = result; } Output: Result is: 20
A closure function has access to the parent scope, even after the parent function has closed so it helps you in making functions attributes capsuled privately while they are accessible also with some restrictions.
JavaScript is an important front-end development language to develop high end and rich featured UI for websites and web apps.
If you have enjoyed our blog on Closures in JavaScript and want to learn advanced JavaScript classes to clear your most advanced concepts like design patterns and object-oriented JavaScript; please let us know in below comment area.