Click here to Skip to main content
13,700,577 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

2.9K views
4 bookmarked
Posted 31 Jul 2017
Licenced CPOL

JavaScript Closures

, 31 Jul 2017
Rate this:
Please Sign up or sign in to vote.
A brief and easy to grasp article on Closures in JavaScript

Introduction

If you have learnt about functions and modules, learning closures should not be a big deal for you. If you just happened to land here and haven't gone through those two topics, that is also perfectly fine. Closures fall in the category of advanced JavaScript concepts but trust me, if you know and understand how inner functions work, understanding closures will be a cakewalk.

For all hard working and curious folks here who hate shortcuts and love to dive deep, I will recommend the post on functions before moving on. For those lazy and 2-minutes maggi lovers kinda dudes, this post will make sure you get the required basic concepts cooked and served right to your plate before jumping to the main course (closures).

Inner Functions

An inner function is fundamentally a "function within a function". JavaScript supports nested functions, that means you can create one or more functions inside a function. The inner functions may again contain functions inside and this nesting can go even deeper. Let's see this with a simple example.

function innerOuterDemo(){
   console.log("The outer function");

   function innerFunction(){
      console.log("The inner function");
   }
   return innerFunction;
}

The function innerOuterDemo contains an inner function named innerFunction that just writes "The inner function" to console. A call to innerOuterDemo will write "The outer function" to console and return the function innerFunction.

var doSomething = innerOuterDemo(); // Logs "The outer function" and returns innerFunction
doSomething(); // Logs "The inner function"

Pretty simple and straightforward. But just keep in mind that once a function finishes the execution and returns, it's no longer in scope. That says when innerOuterDemo gets executed and returns the innerFunction, innerOuterDemo is no longer in scope.

Now that we have covered the basics of function nesting and scope, let's jump right to closures. Consider the example below:

function foodAndMore(){
   var myFood = "Pizza and Pasta";
 
   function getMyFood(){
      return myFood;
   }
 
   return getMyFood;
}
 
var foodILove = foodAndMore();
console.log("I love " + foodILove());

Quite similar to the first illustration except that we have some data (myFood variable) we are playing with. The variable myFood belongs to the outer function foodAndMore but is used inside inner function getMyFood in return statement. Invocation to foodAndMore function returns getMyFood function which is assigned to variable foodILove. When you run the above snippet, it will write the text "I love Pizza and Pasta" to console.

Now what is special here? Remember my words when I said when a function completes its execution, it goes out of scope? If so, shouldn't myFood variable that contains value "Pizza and Pasta" go out of scope when function foodAndMore returns after execution? But if you have seen the output in console which logs "I love Pizza and Pasta", then this is certainly not the case.

Closure

A closure is the combination of an inner function and variables defined at outer scope but accessible to inner function. In other words, a closure is an inner function that can access outer function’s variables. Now let's get hungry and take a glance over our foodie example. As we have already observed, the inner function getMyFood has access to outer function's variable myFood even when outer function has completed its execution and is out of scope. So the combination of function getMyFood and variable myFood is an example of a closure. We can call getMyFood function anytime through a variable reference (e.g. foodILove) and get the value of myFood variable which is "Pizza and Pasta".

In JavaScript, inner functions have access not only to the variables of outer functions but also to their parameters. The next example will prove this right.

function getMultiplier(multiplyBy){
   function multiply(num){
      return multiplyBy * num;
   }
 
   return multiply;
}
 
var multiplyByTwo = getMultiplier(2);
var multiplyByTen = getMultiplier(10);
var twoIntoFive = multiplyByTwo(5); // 10
var tenIntoSix = multiplyByTen(6);  // 60

So inner function multiply has access to the outer function's parameter multiplyBy. Outer function getMultiplier returns a function that can be used as a multiplier function. We are creating two functions multiplyByTwo and multiplyByTen out of it. While invoking any of these two functions, JavaScript runtime remembers the execution environment (arguments to getMultiplier function) and performs the multiplication between the numbers.

Closures are used extensively in JavaScript and JavaScript based libraries and frameworks. Trivial examples are event handling and AJAX calls when you write inline functions as event handler or callbacks. Those inline functions have access to the main (outer) function's variables and parameters.

Here is an example of a button click event handler function (closure) in jQuery. The function has access to count variable and its state even when outer function is not in execution.

$(function(){
   var count = 1;
   $("#counterBtn").Click(function(){ 
                      alert("Your click count is: " + count++);
                    });
});

Closures are also useful in defining public functions that can access private functions and variables in JavaScript's popular module pattern. A simple illustration is given below.

var mathUtility = (function(){
   var count = 1;
 
   function increment(number){
      return number + count;
   }
 
   function decrement(number){
      return number - count;
   }
 
   return {
      nextOf: increment,
      previousOf: decrement
   };
}());
 
var numberAfterFive = mathUtility.nextOf(5);       // 6
var numberBeforeTen = mathUtility.previousOf(10);  // 9

I hope the example above is self explanatory. We are creating a module mathUtility that contains two private functions increment and decrement. Both private functions have access to count variable in outer anonymous function, hence forming closures. We return an object, actually a module named mathUtility containing two public functions nextOf and previousOf that can be used to find next or previous numbers of any given number.

Final Words

Let me not reduce the size of your scrollbar and say the final words. Just remember that JavaScript functions remember their execution environment. JavaScript runtime makes sure that outer function's variables and parameters that were in scope and accessible to inner functions will always be accessible to inner functions.

I tried to keep this post concise, to the point and easy to understand. Leave your comments if you still have doubts or if you find something that can be improved further. Thanks for reading.

You might also be interested in:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Dheeraj Kumar Kesri
Software Developer Apttus
India India
I'm a software developer in Bangalore, India. I have special interest in web development and I blog at www.code-morning.com

You may also be interested in...

Comments and Discussions

 
QuestionNice article and proof of javascript as a non-sensible languuage! Pin
Bob10001-Aug-17 12:06
professionalBob10001-Aug-17 12:06 
AnswerRe: Nice article and proof of javascript as a non-sensible languuage! Pin
Peter_in_27806-Aug-17 20:41
professionalPeter_in_27806-Aug-17 20:41 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180910.1 | Last Updated 31 Jul 2017
Article Copyright 2017 by Dheeraj Kumar Kesri
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid