Blog

Javascript Closures

Mike Lonnborg
June 7th, 2017

A closure is an inner JavaScript function that has access to the outer (enclosing) function's variables—scope. A closure has three scopes which 1) has access to its own scope (variables defined between its curly brackets) 2) has access to the outer function's variables and 3) has access to the global variables.

A basic example of a JavaScript closure:


function showMessage(message) {
​   var x = "Hello ";

   // this inner function has access to the outer function's variables, including the parameter​
   ​function showEntireMessage() {
​       return x + " " + message;
   }
​
   ​return showEntireMessage();
}​

showMessage("World"); // Hello World

Closures are useful because they let you associate some data with a function that operates on that data. This has obvious parallels to object oriented programming, where objects allow us to associate some data (the object's properties) with one or more methods. Consequently, you can use a closure anywhere that you might normally use an object with only a single method. Situations where you might want to do this are particularly common on the web. Much of the code we write in front-end JavaScript is event-based — we define some behavior, then attach it to an event that is triggered by the user (such as a click or a keypress).

Closures store references to the outer function's variables, they do not store the actual value. Closures get more interesting when the value of the outer function's variable changes before the closure is called. This is an important feature, such as this private variables example:


function productId () {
    var productId = 123;
    // We are returning an object with some inner functions​
    // All the inner functions have access to the outer function's variables​
    return {
        getID: function ()  {
            // This inner function will return the UPDATED productId variable​
            // It will return the current value of productId, even after the productId function changes it​
            return productId;  
        },
        setID: function (theNewId)  {
            // This inner function will change the outer function's variable anytime​
            productId = theNewId;                                                                 
        }
    }​
}
​
​var pId = productId(); // At this juncture, the productId's outer function has returned.​
pId.getId(); // 123
pId.setId(456); // Changes the outer function's variable​
pId.getId(); // 456: This returns the updated productId's variable


Some caveats

Prior to the introduction of the let keyword in ECMAScript 2015, a common problem with closures occurred when they were created inside a loop. So if you must use a for loop make sure your clients are running IE9+ and make use of the let keyword as shown in the example below.


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'}
    ];

  for (var i = 0; i < helpText.length; i++) {
    let item = helpText[i];
    document.getElementById(item.id).onfocus = function() {
      showHelp(item.help);
    }
  }
}

setupHelp();

Note: The example above uses let instead of var, so every closure binds the block-scoped variable, meaning that no additional closures are required.