Static Version

Why use "closure"?

One of the greatest features of the JavaScript language is closure. I've discussed this concept some in the "What is This?" article. There I was explaining scope and context. Today I wish to explain about some practical uses of a closure in event based programming as well as compare it to other methods like object orientation to preserve state across event calls.

What is a closure

Again from wikipedia:

In computer science, a closure is a first-class function with free variables that are bound in the lexical environment. Such a function is said to be "closed over" its free variables. A closure is defined within the scope of its free variables, and the extent of those variables is at least as long as the lifetime of the closure itself.

Or the way I understand it intuitively:

A closure is a function defined within another scope that has access to all the variables within the outer scope.

Using closure to hide state

Imagine this piece of code:

greet_plain.js
var sys = require('sys');

function greet(message) {
  sys
.puts(message);
}

function greeter(name, age) {
 
return name + ", who is " + age + " years old, says hi!";
}

// Generate the message
var message = greeter("Bob", 47);

// Pass it explicitly to greet
greet
(message);

We're manually passing the internal state around so that the other functions can get ahold of it. I mean, it works and is really simple, but assuming you never need the generated message string outside of the greet function, what's the point of making the user of the API handle internal data for you. Also what if later on the greet function needed some other data, you would have to change everything to pass along more variables.

Clearly there must be a better way.

My favorite use of closure is to call a function that generates another function or group of functions but hides all the state in private variables within the closure:

greeter.js
var sys = require('sys');

function greeter(name, age) {
 
var message = name + ", who is " + age + " years old, says hi!";

 
return function greet() {
    sys
.puts(message);
 
};
}

// Generate the closure
var bobGreeter = greeter("Bob", 47);

// Use the closure
bobGreeter
();

Note that the greet function is nested within the greeter function. This means it's within the lexical scope of greeter and thus according to the rules of closure has access to the local variables of greeter including message, name, and age.

Using a closure instead of objects

Many people who come to JavaScript are experienced programmers who come from other languages where classes and instances are the common way to handle this encapsulation. JavaScript has something similar in the form of constructor functions and function prototypes.

Classical OO in JavaScript

Consider the following class, it uses a classical constructor with function prototypes to work like a class from other languages.

Since you're using the object itself as the place to store state, all references have to be prefixed with this. It's impossible to hide any variables since everything that accessible to your methods is also publicly readable, writable, and even deletable. Also if you have a function nested inside of anything then this will change on you unless it's explicitly passed through or preserved with a closure. (see the slowGreet method)

Define the class like this:

personclass.js
var sys = require('sys');

// Define the constructor
function Person(name, age) {

 
// Store the message in internal state
 
this.message = name + ", who is " + age + " years old, says hi!";

};

// Define a sync method
Person.prototype.greet = function greet() {
  sys
.puts(this.message);
};

// Define a method with async internals
Person.prototype.slowGreet = function slowGreet() {
 
var self = this; // Use a closure to preserve `this`
  setTimeout
(function () {
    sys
.puts(self.message);
 
}, 1000);
};

// Export this file as a module
module.exports = Person;

And use it like this:

useclass.js
var Person = require('./personclass');

var bob = new Person("Bob", 47);

bob
.greet();

Nice clean OO code right? The good thing is that you get to write your methods outside of the constructor instead of nested inside it. This is a very comfortable pattern and is used by a lot of successful JavaScript projects.

Object factories using closures

This is how I would write this class without using new and prototype. I'll create a factory function that creates a closure and exposes parts of it as public methods. Externally it looks a lot like the class based version, but internally it's 100% a closure and there isn't a this or new in sight.

Define the factory like this:

personfactory.js
var sys = require('sys');

// Define the factory
function newPerson(name, age) {

 
// Store the message in a closure
 
var message = name + ", who is " + age + " years old, says hi!";

 
return {

   
// Define a sync function
    greet
: function greet() {
      sys
.puts(message);
   
},

   
// Define a function with async internals
    slowGreet
: function slowGreet() {
      setTimeout
(function () {
        sys
.puts(message);
     
}, 1000);
   
}

 
};
}

// Export this file as a module
module.exports = newPerson;

And use it like this:

usefactory.js
var newPerson = require('./personfactory');

var tim = newPerson("Tim", 28);

tim
.greet();

I like it! One word of caution though. While this method is quite easy to use, it doesn't perform well when you're creating large numbers of instances. Each instance will create its own version of every function in the object.

Closures for events and callbacks

This is where closures are the most useful. In fact, this is the reason that Ryan Dahl (The creator of node.js) used JavaScript in the first place. C doesn't have closures and it makes non-blocking code difficult to write in C.

The simplest example (which we just saw earlier) is setTimeout. This is a non-blocking function call. The code in the passed in callback won't get called till after the timeout happens. This will be on a completely new stack and the only way to get data into it is through lexical scope and a closure.

Imagine this code snippet:

settimeout.js
var sys = require('sys');

function handle() {
  sys
.puts(message);
}

function setAlarm(message, timeout) {
  setTimeout
(handle, timeout);
}

setAlarm
("Wake UP!", 100);

This won't work, message will be undefined since it's a local variable to setAlarm and doesn't exist outside that function. Instead we need to define the handle function inside of the setAlarm function.

settimeout2.js
var sys = require('sys');

function setAlarm(message, timeout) {

 
// Define handle in the closure
 
function handle() {
    sys
.puts(message);
 
}

  setTimeout
(handle, timeout);
}

setAlarm
("Wake UP!", 100);

As explained in the "What is This?" article, this is especially painful when dealing with setting callbacks. This is because specifying a method of an object as the callback function will cause the function by itself to be the callback, not the object associated with it.

eventobj.js
var Person = require('./personclass'),
    newPerson
= require('./personfactory');

var bob = new Person("Bob", 47);
var jake = new Person("Jake", 17);
var tim = newPerson("Tim", 28);

setTimeout
(bob.greet, 100);
// Outputs: undefined

setTimeout
(tim.greet, 100);
// Outputs: Tim, who is 28 years old, says hi!

// With `this` based objects you have to manually bind the function
// This works
setTimeout
(function () {
  jake
.greet();
}, 100);
// Outputs: Jake, who is 17 years old, says hi!

Interesting thing about JavaScript is that functions are first-class values. The whole this context helps in designing classical OO API's, but you have to remember that it's only assigned on function call, it's not something tied to the function itself. Variables from the closure, however are part of the function itself, no matter how it's called.


View the discussion thread.blog comments powered byDisqus