JavaScript Closures Demystified

Tweet

Closures are a somewhat advanced, and often misunderstood feature of the JavaScript language. Simply put, closures are objects that contain a function and a reference to the environment in which the function was created. However, in order to fully understand closures, there are two other features of the JavaScript language that must first be understood―first-class functions and inner functions.

First-Class Functions

In programming languages, functions are considered to be first-class citizens if they can be manipulated like any other data type. For example, first-class functions can be constructed at runtime and assigned to variables.  They can also be passed to, and returned by other functions. In addition to meeting the previously mentioned criteria, JavaScript functions also have their own properties and methods. The following example shows some of the capabilities of first-class functions. In the example, two functions are created and assigned to the variables “foo” and “bar”. The function stored in “foo” displays a dialog box, while “bar” simply returns whatever argument is passed to it. The last line of the example does several things. First, the function stored in “bar” is called with “foo” as its argument. “bar” then returns the “foo” function reference. Finally, the returned “foo” reference is called, causing “Hello World!” to be displayed.

var foo = function() {
  alert("Hello World!");
};

var bar = function(arg) {
  return arg;
};

bar(foo)();

Inner Functions

Inner functions, also referred to as nested functions, are functions that are defined inside of another function (referred to as the outer function). Each time the outer function is called, an instance of the inner function is created. The following example shows how inner functions are used. In this case, add() is the outer function. Inside of add(), the doAdd() inner function is defined and called.

function add(value1, value2) {
  function doAdd(operand1, operand2) {
    return operand1 + operand2;
  }

  return doAdd(value1, value2);
}

var foo = add(1, 2);
// foo equals 3

One important characteristic of inner functions is that they have implicit access to the outer function’s scope. This means that the inner function can use the variables, arguments, etc. of the outer function. In the previous example, the “value1″ and “value2″ arguments of add() were passed to doAdd() as the “operand1″ and “operand2″ arguments. However, this is unnecessary because doAdd() has direct access to “value1″ and “value2″. The previous example has been rewritten below to show how doAdd() can use “value1″ and “value2″.

function add(value1, value2) {
  function doAdd() {
    return value1 + value2;
  }

  return doAdd();
}

var foo = add(1, 2);
// foo equals 3

Creating Closures

A closure is created when an inner function is made accessible from outside of the function that created it. This typically occurs when an outer function returns an inner function.  When this happens, the inner function maintains a reference to the environment in which it was created.  This means that it remembers all of the variables (and their values) that were in scope at the time. The following example shows how a closure is created and used.

function add(value1) {
  return function doAdd(value2) {
    return value1 + value2;
  };
}

var increment = add(1);
var foo = increment(2);
// foo equals 3

There are a number of things to note about this example.

  • The add() function returns its inner function doAdd(). By returning a reference to an inner function, a closure is created.
  • “value1″ is a local variable of add(), and a non-local variable of doAdd(). Non-local variables refer to variables that are neither in the local nor the global scope.  “value2″ is a local variable of doAdd().
  • When add(1) is called, a closure is created and stored in “increment”. In the closure’s referencing environment, “value1″ is bound to the value one.  Variables that are bound are also said to be closed over. This is where the name closure comes from.
  • When increment(2) is called, the closure is entered. This means that doAdd() is called, with the “value1″ variable holding the value one. The closure can essentially be thought of as creating the following function.
function increment(value2) {
  return 1 + value2;
}

When to Use Closures

Closures can be used to accomplish many things. They are very useful for things like configuring callback functions with parameters. This section covers two scenarios where closures can make your life as a developer much simpler.

Working With Timers

Closures are useful when used in conjunction with the setTimeout() and setInterval() functions. To be more specific, closures allow you to pass arguments to the callback functions of setTimeout() and setInterval(). For example, the following code prints the string “some message” once per second by calling showMessage().

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Closures</title>
  <meta charset="UTF-8" />
  <script>
    window.addEventListener("load", function() {
      window.setInterval(showMessage, 1000, "some message<br />");
    });

    function showMessage(message) {
      document.getElementById("message").innerHTML += message;
    }
  </script>
</head>
<body>
  <span id="message"></span>
</body>
</html>

Unfortunately, Internet Explorer does not support passing callback arguments via setInterval(). Instead of displaying “some message”, Internet Explorer displays “undefined” (since no value is actually passed to showMessage()). To work around this issue, a closure can be created which binds the “message” argument to the desired value. The closure can then be used as the callback function for setInterval(). To illustrate this concept, the JavaScript code from the previous example has been rewritten below to use a closure.

window.addEventListener("load", function() {
  var showMessage = getClosure("some message<br />");

  window.setInterval(showMessage, 1000);
});

function getClosure(message) {
  function showMessage() {
    document.getElementById("message").innerHTML += message;
  }

  return showMessage;
}

Emulating Private Data

Many object-oriented languages support the concept of private member data. However, JavaScript is not a pure object-oriented language and does not support private data. But, it is possible to emulate private data using closures. Recall that a closure contains a reference to the environment in which it was originally created―which is now out of scope. Since the variables in the referencing environment are only accessible from the closure function, they are essentially private data.

The following example shows a constructor for a simple Person class. When each Person is created, it is given a name via the “name” argument.  Internally, the Person stores its name in the “_name” variable. Following good object-oriented programming practices, the method getName() is also provided for retrieving the name.

function Person(name) {
  this._name = name;

  this.getName = function() {
    return this._name;
  };
}

There is still one major problem with the Person class. Because JavaScript does not support private data, there is nothing stopping somebody else from coming along and changing the name. For example, the following code creates a Person named Colin, and then changes its name to Tom.

var person = new Person("Colin");

person._name = "Tom";
// person.getName() now returns "Tom"

Personally, I wouldn’t like it if just anyone could come along and legally change my name. In order to stop this from happening, a closure can be used to make the “_name” variable private. The Person constructor has been rewritten below using a closure. Note that “_name” is now a local variable of the Person constructor instead of an object property. A closure is formed because the outer function, Person() exposes an inner function by creating the public getName() method.

function Person(name) {
  var _name = name;

  this.getName = function() {
    return _name;
  };
}

Now, when getName() is called, it is guaranteed to return the value that was originally passed to the constructor. It is still possible for someone to add a new “_name” property to the object, but the internal workings of the object will not be affected as long as they refer to the variable bound by the closure.  The following code shows that the “_name” variable is, indeed, private.

var person = new Person("Colin");

person._name = "Tom";
// person._name is "Tom" but person.getName() returns "Colin"

When Not to Use Closures

It is important to understand how closures work and when to use them. It is equally important to understand when they are not the right tool for the job at hand. Overusing closures can cause scripts to execute slowly and consume unnecessary memory. And because closures are so simple to create, it is possible to misuse them without even knowing it.  This section covers several scenarios where closures should be used with caution.

In Loops

Creating closures within loops can have misleading results. An example of this is shown below. In this example, three buttons are created. When “button1″ is clicked, an alert should be displayed that says “Clicked button 1″.  Similar messages should be shown for “button2″ and “button3″.  However, when this code is run, all of the buttons show “Clicked button 4″. This is because, by the time one of the buttons is clicked, the loop has finished executing, and the loop variable has reached its final value of four.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Closures</title>
  <meta charset="UTF-8" />
  <script>
    window.addEventListener("load", function() {
      for (var i = 1; i < 4; i++) {
        var button = document.getElementById("button" + i);

        button.addEventListener("click", function() {
          alert("Clicked button " + i);
        });
      }
    });
  </script>
</head>
<body>
  <input type="button" id="button1" value="One" />
  <input type="button" id="button2" value="Two" />
  <input type="button" id="button3" value="Three" />
</body>
</html>

To solve this problem, the closure must be decoupled from the actual loop variable. This can be done by calling a new function, which in turn creates a new referencing environment. The following example shows how this is done. The loop variable is passed to the getHandler() function. getHandler() then returns a closure that is independent of the original “for” loop.

function getHandler(i) {
  return function handler() {
    alert("Clicked button " + i);
  };
}

window.addEventListener("load", function() {
  for (var i = 1; i < 4; i++) {
    var button = document.getElementById("button" + i);

    button.addEventListener("click", getHandler(i));
  }
});

Unnecessary Use in Constructors

Constructor functions are another common source of closure misuse. We’ve seen how closures can be used to emulate private data. However, it is overkill to implement methods as closures if they don’t actually access the private data. The following example revisits the Person class, but this time adds a sayHello() method which doesn’t use the private data.

function Person(name) {
  var _name = name;

  this.getName = function() {
    return _name;
  };

  this.sayHello = function() {
    alert("Hello!");
  };
}

Each time a Person is instantiated, time is spent creating the sayHello() method. If many Person objects are created, this becomes a waste of time.  A better approach would be to add sayHello() to the Person prototype. By adding to the prototype, all Person objects can share the same method.  This saves time in the constructor by not having to create a closure for each instance. The previous example is rewritten below with the extraneous closure moved into the prototype.

function Person(name) {
  var _name = name;

  this.getName = function() {
    return _name;
  };
}

Person.prototype.sayHello = function() {
  alert("Hello!");
};

Things to Remember

  • Closures contain a function and a reference to the environment in which the function was created.
  • A closure is formed when an outer function exposes an inner function.
  • Closures can be used to easily pass parameters to callback functions.
  • Private data can be emulated by using closures.  This is common in object-oriented programming and namespace design.
  • Closures should be not overused in constructors.  Adding to the prototype is a better idea.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.clearfirestudios.com Jon Thomas

    This was a great help. Unfortunately, some things are still not clicking for me. Still waiting for my ‘aha’ moment. I fell like I understand functions within functions, local variables etc, but I still get lost when creating variables that call the outer function, and then another variable that uses that previous variable to access the inner function. There’s still a disconnect for me on how all the data moves and gets passed around. How an argument knows what it’s value is, etc. Hopefully after 1 or 2 more reads through it will begin to click.

  • Pascal

    Thanks for the clear explanation, really useful.

  • http://webdeavour.co.uk Lee Kowalkowski

    A closure exists whether there are inner functions or not. A closure is simply a means for a function to have access to non-local variables. A mechanism which communicates to a function “Here’s what you can access” – so the contents of a function’s closure are affected by what’s in scope at the time the function was created.

    What you are utilising is the fact that data is not automatically discarded whilst there are still references to it, thereby extending the lifetime of that data beyond the lifetime of the function that created it. i.e. because an inner function’s closure references all the available non-local variables (e.g. local to the outer function), AND there are still references to the inner function.

    In your example, you keep the references alive because your inner anonymous functions are assigned to properties of the DOM or ‘this’, which are not local. So once your outer function has completed, there are still references to your inner functions, and your inner functions have closures over scope that would normally have been discarded.

    Are you sure about prototype? I don’t think a single method is shared between all your objects, because a prototype is the blueprint for creating new objects. If you want to share a single instance of something between all your objects, you can create it as an immediate property of the function. e.g. (Person.sayHello): http://jsfiddle.net/uXRfK/

    When you used prototype to create methods in your example, you just did it in a different execution context with a different scope (which could have been part of another, separate closure). I don’t think there’s any performance benefit because all of a functions inner functions within the same scope chain will share the same closure object, because they are all created together: http://jsperf.com/function-in-object-vs-prototype/2

    So for readability, it would be better not to use prototype just to ‘avoid closures’, that sounds like a maintenance annoyance, having to move a function in or out depending on whether or not you now require access to ‘private variables’. Leave them in if that’s where they logically belong.

    • http://www.cjihrig.com Colin Ihrig

      A closure is a function and its referencing environment. Of course the referencing environment is affected by the current scope. Your comment implies that you disagree with this generally accepted uses of closures.

      Yes, the prototype is shared. There is a difference between a variable referenced with “this” and a prototype variable (your jsfiddle example does not indicate this). Variables using “this” belong to specific instances. If an instance does not contain a variable, then the prototype chain is traversed. The prototype is therefore shared because it adds a method to all instances, even those that have already been created. Your example is actually creating a static variable (Foo.instances).

      Also, your object vs. prototype example seems to indicate that there is generally a performance benefit to using the prototype (with the exception of the outdated version of Chrome). However, I was originally referring to the overhead of executing additional code within the constructor. Each time the constructor is invoked, you would be defining all of the same properties. This is the performance hit I was referring to. By updating the prototype, the code only needs to be executed once.

      • Lee Kowalkowski

        Thank you.

        Oh so when I did this.instances (which is not defined), it falls over to Foo.prototype.instances?
        A-ha! Therefore if I incremented Foo.prototype.instances instead, *that* would be incrementing the shared instance? That’s a bit bleeding obvious now!

        Prototype demystified. (That was going to be my original comment, incidentally, but I wrote the jsfiddle to make sure I understood it right, but got myself muddled – but now I feel fantastic!)

        I don’t disagree with the uses of closures, I just find most explanations a tough read (even after I learned closures). I expect you do to, hence your article, because there are tons of “this is what a closure is” articles out there.

        I think the thing that troubles me most is the “A closure is created when an inner function is made accessible from outside of the function that created it.” It’s just that an inner function is not necessary to create a closure, only to keep one alive and therefore prove it existed (i.e. you need an inner function to allow the original context to be re-entered).

        There just seems to be a blur between explaining what a closure actually is and how to therefore make use of them. It’s just that a closure exists even for top-level functions, and garbage collection plays just as important a part in describing how to deliberately use closures to solve a programming problem.

        I fear that explaining/understanding closures might be similar to the old “To understand recursion, you must first understand recursion”, that’s just how it feels.

        • http://www.cjihrig.com Colin Ihrig

          I totally agree with you about explaining what a closure is and how to make use of it.

          When you write “this.instances”, it adds an “instances” variable to the current object. It doesn’t touch the prototype. I found this additional post on Stack Overflow that discusses the issue in more detail. Also, try running this code through jsfiddle. I think it might help.

          function Foo() {

          var id = parseInt(Math.random() * 1000000);

          this.toString = function() {
          return [this.instances, id].toString();
          }

          }

          var x = new Foo();
          var y = new Foo();

          document.write("x.instances = " + x.instances + "");
          document.write("y.instances = " + y.instances + "");

          Foo.prototype.instances = 1;
          document.write("x.instances = " + x.instances + "");
          document.write("y.instances = " + y.instances + "");

          x.instances = 4;
          document.write("x.instances = " + x.instances + "");
          document.write("y.instances = " + y.instances + "");

          • http://webdeavour.co.uk Lee Kowalkowski

            Exactly! Your comment “If an instance does not contain a variable, then the prototype chain is traversed.” was sufficient. I expected this.instances++ to refer to prototype.instances, which it did for retrieving the value (because this.instances was undefined), but it then shadowed the prototype upon assignment. Which makes sense when expanding the increment to this.instances = this.instances + 1.

            Great!