JavaScript for C# developers: the Module Pattern (part 1)

If you recall, JavaScript closures are an extremely powerful concept in the language. By using JavaScript’s rather peculiar scoping rules, closures are a way of creating private variables and functionality for an object. The module pattern builds upon this feature.

StopwatchA quick recap on scope in JavaScript may be in order. Scope is the means by which programmers limit the visibility and the lifetime of their variables and parameters. Without scope, all variables would be global and visible everywhere. In C#, scope is introduced by braces: you can declare a new variable inside some code in braces — a block — and that variable would not be visible outside the block, and in fact would be destroyed once execution reaches the closing brace. These braces can be the braces surrounding the code in a method, or they can be the braces delineating a block for an if or a for statement, and so on. The essence of scope in C# is: declare a variable inside a block and it won't be visible outside the braces enclosing the block. (For full details about scope in C# you should read section 3.7 of The C# Programming Language (Fourth Edition) by Hejlsberg et al. There’s roughly eight pages of discussion on scope.)

In JavaScript, there is one basic rule: functions define scope. If you declare a variable in a function, it is visible anywhere inside that function, including inside any nested functions, even before it was declared. It is not visible outside the function. Since nested functions are also variables, they will also be visible anywhere in the enclosing function, even before they are declared. In essence, JavaScript hoists all variables to the top of the enclosing function so that they are declared before they are set with a value. This is like the lexical structure of Pascal with its var blocks, except that this hoisting occurs automatically in JavaScript.

Note that by nested functions, I mean functions nested in a lexical sense not in an execution sense. In other words, if function A calls function B, it doesn’t mean that B can suddenly ‘see’ the variables declared in A. For that to happen, B must be coded within the source code for A. It’s the lexical nesting that provides scope.

Let’s see this in code:

var outerFunc = function (paramOuter) {
  // Visible: paramOuter, varOuter
  //          nestedFunc1, nestedFunc2
  var varOuter = 42;

  var nestedFunc1 = function (paramNested1) {
    // Visible: paramOuter, varOuter
    //          nestedFunc1, nestedFunc2
    //          paramNested1, varNested1,
    //          nestedFunc1inner
    var varNested1 = false;

    var nestedFunc1inner = function () {
      // Visible: paramOuter, varOuter
      //          nestedFunc1, nestedFunc2
      //          paramNested1, varNested1,
      //          nestedFunc1inner, inner1
      var inner1 = "hello";

    };
  };

  var nestedFunc2 = function (paramNested2) {
    // Visible: paramOuter, varOuter
    //          nestedFunc1, nestedFunc2
    //          paramNested2, varNested2
    var varNested2 = false;

  };
};

It’s not exactly an example of some edifying code, but it gets the point across. If you look at the nestedFunc1inner function, you can see that all of the variables from the outer function are in scope as well as all the variables from the immediate parent function as well.

The nifty thing about these scoping rules is how well it plays along with closures. A closure encapsulates a function’s environment so that it can continue to exist as an object even after the function terminates. In C#, you see this most of all with lambda expressions and anonymous delegates, but with JavaScript you see it all over the place. jQuery is, in essence, one gigantic closure.

Let’s suppose we have to write a stopwatch object, which we’re going to use to time sections of our JavaScript code. The object should have a start() method that starts the stopwatch ticking, a stop() method to stop the watch (and which should also return the number of milliseconds elapsed). Without closures we’d probably write something like this:

var stopwatch = {
  startTime: -1,

  now: function () {
    return +new Date();
  },

  start: function () {
    this.startTime = this.now();
  },

  stop: function () {
    if (this.startTime === -1) {
      return 0;
    }
    var elapsedTime = this.now() - this.startTime;
    this.startTime = -1;
    return elapsedTime;
  }
};

Notice that I have a helper method called now() (that construction of +new Date() looks too weird in actual code – what does it do again?) as well as an internal field that records the start time of the stopwatch. Unfortunately although this object nicely encapsulated these two members, they are public, fully visible. We have not hidden them. A user of the stopwatch object could access them, change the variable, replace them, whatever. Also, I hate to say it, but all those required references to this doesn’t half obfuscate the code and make it long-winded.

Enter the module pattern. With the module pattern, we create an anonymous function and execute it automatically. The function will return an object that will be our stopwatch object. Let’s look at this step-by step. First we create the outer anonymous function and auto-execute it. For now we’ll have the function return an empty object.

var stopwatch = (function () {
  // other code to be added here
  return {
    // define some fields
  };
}());

Nothing too drastic so far, I’m sure you’ll agree. Now the fun bit starts. Let’s add back the original stopwatch code, altering it so that it makes sense as local variables and nested functions.

var stopwatch = (function () {
  var startTime = -1,

  now = function () {
    return +new Date();
  },

  start = function () {
    startTime = now();
  },

  stop = function () {
    if (startTime === -1) {
      return 0;
    }
    var elapsedTime = now() - startTime;
    startTime = -1;
    return elapsedTime;
  };

  return {
    // define some fields
  };
}());

As you can see all of those annoying this references have gone since there is no enclosing object any more. Instead we can rely on function scope to resolve references to variables. For example, in the start() function we can reference the outer anonymous function’s startTime local variable. For that matter, the same applies to the stop() function. The final step is to make sure that the returned object has the required two methods, start() and stop().

var stopwatch = (function () {
  var startTime = -1,

  now = function () {
    return +new Date();
  },

  start = function () {
    startTime = now();
  },

  stop = function () {
    if (startTime === -1) {
      return 0;
    }
    var elapsedTime = now() - startTime;
    startTime = -1;
    return elapsedTime;
  };

  return {
    start: start,
    stop: stop
  };
}());

The code that creates the new returned object looks a little weird until you read it as “this new object has a stop property whose value is the internal stop() function object, etc.”

The returned object makes use of the closure formed by the anonymous function. The object’s two properties (methods) will call the nested functions inside the closure and those, in turn, will make use of the outer function’s local variable startTime. We’ve essentially created some private members: a local variable and a now() function. These two members are inaccessible outside of the closure.

It must be admitted that the code as written assumes that our stopwatch object is going to be a singleton; after all, we’re auto-executing an anonymous function and it’s hard to do that twice in a row. If you have need of several stopwatches, then the best thing is to assign that anonymous function to a variable called createStopwatch, and then you can call it ad nauseam to create as many stopwatches as you’d like.

var createStopwatch = function () {
  // same code as before
  return {
    start: start,
    stop: stop
  };
};

var stopwatch1 = createStopwatch();
var stopwatch2 = createStopwatch();

Next time, we’ll take a look at how to augment an object created with the module pattern.

(Part 2, Part 3 of this series.)

Album cover for BoomaniaNow playing:
Boo, Betty - Doin' the do (7" radio mix)
(from Boomania)


Loading similar posts...   Loading links to posts on similar topics...

4 Responses

 avatar
#1 David Robbins said...
03-Jan-12 6:48 AM

Nice post - I look forward to reading more. We have a team of C# devs who dabble in jQuery, but beyond that our fundamentals are in need of development. This will be a good series for us.

BTW and off topic - I like the "Now playing ..." of you post. Music can really lighten the tone. Have you considered embedding music in your posts directly? If so, I found a guy who does this Grooveshark. Here's the link:

activeengine.wordpress.com/.../how-to-embed-gr

julian m bucknall avatar
#2 julian m bucknall said...
03-Jan-12 11:56 AM

David: thanks for the thanks!

Re: the "Now playing...." links. I have them mainly because I wrote it as an add-in for Windows Live Writer (the blogging editor I use). I'll have to investigate how to incorporate Grooveshark into both that and the blogging engine used on this site (GraffitiCMS). Shoudn't be too difficult -- famous last words...

Cheers, Julian

 avatar
#3 Tom McKearney said...
13-Jan-12 11:06 AM

If you want to get extra Closure-y, you could make the last bit:

var createStopwatch = (function () {
    // same code as before
    return function(){
        start: start,
        stop: stop
    };
})();
var stopwatch1 = createStopwatch();
var stopwatch2 = createStopwatch();
julian m bucknall avatar
#4 julian m bucknall said...
13-Jan-12 11:15 AM

Tom: Thanks! Yet another way to do this and, as you said, nicely "closure-y" :).

Cheers, Julian

Leave a response

Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.

  •  Emphasize with italics: surround word with underscores _emphasis_
  •  Emphasize strongly: surround word with double-asterisks **strong**
  •  Link: surround text with square brackets, url with parentheses [text](url)
  •  Inline code: surround text with backticks `IEnumerable`
  •  Unordered list: start each line with an asterisk, space * an item
  •  Ordered list: start each line with a digit, period, space 1. an item
  •  Insert code block: start each line with four spaces
  •  Insert blockquote: start each line with right-angle-bracket, space > Now is the time...
Preview of response