One of the shortcomings of JavaScript objects is the lack of support for private members. The ability to create private members makes external API s 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 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.

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!'

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

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'