The module pattern in JavaScript

Let’s talk about organizing our code. There’s never just one way to accomplish something with code. This is both great, and sort of paralyzing. How do you choose?

A beginning programmer writes her programs like an ant builds her hill, one piece at a time, without thought for the bigger structure. Her programs will be like loose sand. They may stand for a while, but growing too big they fall apart.

Realizing this problem, the programmer will start to spend a lot of time thinking about structure. Her programs will be rigidly structured, like rock sculptures. They are solid, but when they must change, violence must be done to them.

The master programmer knows when to apply structure and when to leave things in their simple form. Her programs are like clay, solid yet malleable.

Master Yuan-Ma, The Book of Programming (Source)

Design patterns

Design patterns in JavaScript are documented approaches — or frameworks — for solving problems and structuring code. They are tried and true, reusable, and improve readability — for yourself and others reading your code.

From Addy Osmani’s “Learning JavaScript Design Patterns“–

A pattern is a reusable solution that can be applied to commonly occurring problems in software design – in our case – in writing JavaScript web applications.

Patterns are not an exact solution. It’s important that we remember the role of a pattern is merely to provide us with a solution scheme.

The module pattern is one such pattern. Before we look at this pattern, let’s very briefly refresh on the concept of closure.

Closure

A closure is when a function remembers the context in which it was created, and still has access to local variables, even when that function is executed in a different context — or scope.

For example:

function sayHi(name) {
  var greetingText = "Hi there, ";
  
  function speakGreeting(){
    return greetingText + name; 
  } 
 
  return speakGreeting() 
} 

sayHi('Cass'); 
  //=> "Hi there, Cass" 

The closure (speakGreeting) still has access to the outer function’s variables (here, ‘greetingText’) and parameters (here, ‘name’).

Module pattern

Modules help keep our code neatly organized, and optimized for reuse. They also, by making use of closure, allow us to selectively obscure certain details and expose — or make available — selected functionality.

Keeping the concept of closure in mind, we’ll expand our example to reflect a simple implementation of a module.

function sayHi() {
  var greetingText = "Hi there, ";
  
  function speakGreeting(name){
    return greetingText + name; 
  }

  function shoutGreeting(name){
    return greetingText.toUpperCase() + name.toUpperCase();
  }

  function sayName(name){
    return name;
  }
 
  return {
    speakGreeting: speakGreeting,
    shoutGreeting: shoutGreeting,
    sayName: sayName
  }
} 

var speak = sayHi();

speak.speakGreeting('Cass'); 
  //=> "Hi there, Cass"

speak.shoutGreeting('Dean'); 
  //=> "HI THERE, DEAN"

speak.sayName('Crowley'); 
  //=> "Crowley" 

The ‘speakGreeting’ and ‘shoutGreeting’ functions close over the local variable ‘greetingText’. After executing the outer function ‘sayHi()’ and assigning the returned object to the variable ‘speak’, references to our inner functions ‘speakGreeting’, ‘shoutGreeting’, and ‘sayName’ are available as methods on ‘speak’.

What we are doing here is creating an API. Let’s look at a slightly modified example that makes that more clear.

var module = (function outer() {
  var privateVar = "Hi there, ";
  
  function publicFn1(name){
    return privateVar + name; 
  }

  function publicFn2(name){
    return privateVar.toUpperCase() + name.toUpperCase();
  }

  function publicFn3(name){
    return name;
  }
 
  var publicAPI = {
    publicFn1: publicFn1,
    publicFn2: publicFn2,
    publicFn3: publicFn3
  };

  return publicAPI;
})(); 

module.publicFn1('Cass'); 
  //=> "Hi there, Cass"

module.publicFn2('Dean'); 
  //=> "HI THERE, DEAN"

module.publicFn3('Crowley'); 
  //=> "Crowley" 

What has changed?

  • We are immediately invoking our ‘outer’ function and assigning the returned object to ‘module’. This is useful when multiple instances aren’t needed
  • Within the ‘outer’ function, we assign the object we are returning to var ‘publicAPI’ and return ‘publicAPI’. This makes clear to anyone reading our code (ourselves included) that we are exposing these methods

The functional result, however, is essentially the same.

Modules are like lego pieces — little units that can be used once, or over and over, depending on what you need and where it’s needed, to build larger, more complex structures — except you can form any piece you need, to your own specifications.

lego pieces

**This was slowly and painfully written in Dvorak. Hooray for irrational commitment.

Further reads and sources:

Closure reads:

Module pattern reads:

Leave a Reply

Your email address will not be published. Required fields are marked *