Module Pattern in JavaScript and CoffeeScript

Module Pattern in JavaScript and CoffeeScript

One of the shortcomings of JavaScript objects is the lack of support for private members. The ability to create private members makes external APIs more meaningful and helps keep code more manageable and DRY.

The Module Pattern, pioneered by Douglas Crockford while building the YUI library, is a mechanism that allows for creating public and private members in JavaScript.

This post looks at the pattern in both JavaScript and CoffeScript.

The object literal

The foundational element of the Module Pattern is the object literal, which provides the ability to create instances of objects without instantiating them.

One of the big wins provided by object literals is the ability to add namespaces to your JavaScript code. When you declare a variable outside of an object literal or function the variable is assigned to the window object. In this example, the window object, which represents the open browser window, can be thought of as an implied global namespace. However, writing variables and functions in the default window namespace can be problematic.

Namespaces

JavaScript:

// on the window object
aFunction = function() {
  console.log('My function');
}

aFunction = function() {
  console.log('I just overwrote my original function!');
}

aFunction(); // 'I just overwrote my original function!'

// taking advantage of object literals to provide namespaces
Namespace = {}; AnotherNamespace = {};

Namespace.aFunction = function() {
  console.log('My function');
}

AnotherNamespace.aFunction = function() {
  console.log('I did not overwrite my original function!');
}

Namespace.aFunction(); // 'My function'
AnotherNamespace.aFunction(); // 'I did not overwrite my original function!'

As you’ll notice below we have to explicitly declare variables on window in CoffeeScript. This is because CoffeeScript wraps all code in a self-executing function to make it difficult to accidentally declare variables on window.

CoffeeScript:

// on the window object
window.aFunction = ->
  console.log(‘My function’)

window.aFunction = ->
  console.log('I just overwrote my original function!')

window.aFunction() // 'I just overwrote my original function!'

// taking advantage of object literals to provide namespaces
window.Namespace = {};
window.AnotherNamespace = {};

Namespace.aFunction = ->
  console.log('My function')

AnotherNamespace.aFunction = ->
  console.log('I did not overwrite my original function!')

Namespace.aFunction() // prints 'My function'
AnotherNamespace.aFunction() // 'I did not overwrite my original function!'

Closures

Now that we’ve covered object literals and namespaces let’s take a look at the real power the Module Pattern provides. Using JavaScript’s closures, the methods and variables can be declared not publicly accessible.

JavaScript:

Calculator = {};

Calculator.arithmetic = function() {
  var prettyResultText = 'The answer is:';

  var printResult = function(answer) {
    console.log(answer);
  }

  return {
    add: function(addendOne, addendTwo) {
      var sum = addendOne + addendTwo;
      printResult(prettyResultText + sum);
    }
  };
}

CoffeeScript:

window.Calculator = {}

Calculator.arithmetic = ->
  prettyResultText = 'The answer is: '

  printResult = (answer) ->
     console.log(answer)

  add: (addendOne, addendTwo) ->
    sum = addendOne + addendTwo
    printResult(prettyResultText + sum)

In the example above, there is a function object that behaves similarly to a class.

JavaScript:

var basicCalc = Calculator.arithmetic();

basicCalc.add(1, 2); // 'The answer is: 3'
basicCalc.printResult(”); // TypeError: Object #<object> has no method 'privateFunction'
basicCalc.prettyResultText; // undefined

CoffeeScript:

basicCalc = Calculator.arithmetic()

basicCalc.add 1, 2 // 'The answer is: 3'
basicCalc.printResult '' // TypeError: Object #<object> has no method 'privateFunction'
basicCalc.prettyResultText // undefined

Taking advantage of a self-executing function and the Module Pattern, we can define an object that behaves like a singleton with private members.

JavaScript:

Calculator = {};

Calculator.arithmetic = (function() {
  var prettyResultText = 'The answer is: ';

  var printResult = function(answer) {
    console.log(answer);
  }

  return {
    add: function(addendOne, addendTwo) {
      var sum = addendOne + addendTwo;
      printResult(prettyResultText + sum);
    }
  };
})();

CoffeeScript:

window.Calculator = {}

Calculator.arithmetic = (->
  prettyResultText = 'The answer is: '

  printResult = (answer) ->
    console.log(answer)

  add: (addendOne, addendTwo) ->
    sum = addendOne + addendTwo
    printResult(prettyResultText + sum)
)()

In the above example our very basic calculator will behave the same, but we’ll only ever have one instance.

JavaScript:

Calculator.arithmetic(); // TypeError: object is not a function
Calculator.arithmetic.add(1, 2); // The answer is: 3

CoffeeScript:

Calculator.arithmetic() // TypeError: object is not a function
Calculator.arithmetic.add 1, 2 // The answer is: 3

Self-executing functions

We can also use self-executing functions to create instances of prototypes that share private members.

JavaScript:

Calculator = {};

(function() {
  var prettyResultText = 'The answer is: ';

  var printResult = function(answer) {
    console.log(answer);
  }

  Calculator.arithmetic = function() {
    return {
      add: function(addendOne, addendTwo) {
        var sum = addendOne + addendTwo;
        printResult(prettyResultText + sum);
      }
    }
  };

  Calculator.calculus = function() {
    return {
      derive: function(base, exponent) {
        printResult(prettyResultText + exponent + ' * ' + base);
      }
    }
  };
})();

CoffeeScript:

window.Calculator = {};

(->
  prettyResultText = 'The answer is: '

  printResult = (answer) ->
    console.log(answer)

  Calculator.arithmetic = ->
    add: (addendOne, addendTwo) ->
      sum = addendOne + addendTwo
      printResult(prettyResultText + sum)

  Calculator.calculus = ->
    derive: (base, exponent) ->
      printResult(prettyResultText + exponent + ' * ' + base)
)()

Above we’ve added an overly simplified calculus calculator to our arsenal. Notice that both our arithmetic and calculus calculators share our private methods.

JavaScript:

var simple = Calculator.arithmetic();
var complex = Calculator.calculus();

simple.add(1, 2); // 'The answer is: 3'
complex.derive('x', 2); // 'The answer is: 2 * x'

CoffeeScript:

simple = Calculator.arithmetic()
complex = Calculator.calculus()

simple.add 1, 2 // 'The answer is: 3'
complex.derive 'x', 2 // 'The answer is: 2 * x'

The Module Pattern helps keep your JavaScript code safe from collision and better organized. Exposing a concise public API can make your JavaScript easier to read. Using the Module Pattern requires additional effort up front, but pays for itself in reduced maintenance down the line.

Britt Ballard Developer

Hound reviews Ruby and CoffeeScript code for style violations and comments on your GitHub pull requests. Free for open source repos.