JavaScript: Closures and the Module Pattern

by Larry Spencer Monday, June 3, 2013 8:33 PM

This is the first in a series of posts written for people who may have used JavaScript for client-side validation or UI tweaking, but not to structure a whole application.

In any programming language, once the work gets large, it's time to hide some of the complexity. That's what the JavaScript module pattern and the related concept of closure can do. And they do it in a straightforward and powerful way.

Consider the following code (available here as a JSFiddle).

 

HTML Excerpt

 

<body>
    <p>Spaceship #1 is going to <span id="spaceship1"></span>.</p>
    <p>Spaceship #2 is going to <span id="spaceship2"></span>.</p>
</body>

 

JavaScript

 

var spaceship = function () {
    var destination = 'nowhere';
    return {
        setDestination: function (dest) {
            destination = dest;
        },
        getDestination: function () {
            return destination;
        }
    };
};

var s1 = spaceship();
var s2 = spaceship();
s1.setDestination('Mars');
s2.setDestination('Jupiter');
$('#spaceship1').text(s1.getDestination());
$('#spaceship2').text(s2.getDestination());

 

Result

 

Spaceship #1 is going to Mars.

Spaceship #2 is going to Jupiter.

 

The spaceship function is an example of the JavaScript module pattern. Douglas Crockford's definition of module is a function or object that presents an interface but that hides its state and implementation. How does the code above constitute a module?

The spaceship function returns an object that has two methods. These are the interface presented to the outside world. 

The destination variable constitutes the state of the object.

What makes this more than a little interesting is that destination is not part of the returned object. In fact, you would be forgiven for thinking that it vanishes once the spaceship function returns. After all, it is local to the function so why should it still be available once the function returns? But it is! This is closure at work. JavaScript captures all the variables in the context of the returned object's two functions (just destination in this case) and makes them available even after they would otherwise have gone out of scope.

It's important to realize that a separate copy of the destination variable is captured each time the closure takes place. That's why the first spaceship is still going to Mars even after the second one is set to go to Jupiter.

What makes this pattern useful for structuring large JavaScript programs is that the variable in the outer function is completely encapsulated. It can only be accessed through the returned object.

Next time, we will see how to extend the module pattern one more step. By adding a level of indirection, we can encapsulate variables for all instances of the module to share.

Tags: , , ,

All | General

About the Author

Larry Spencer

Larry Spencer develops software with the Microsoft .NET Framework for ScerIS, a document-management company in Sudbury, MA.