February 17th, 2016

When working on large scale, enterprise applications, developers inevitably face the challenge of protecting their code from accidentally being overwritten by other dev teams. To avoid potential conflicts, I’ll often use the Revealing Module Pattern (RMP) when structuring my JavaScript (JS) to ensure that my code is private and protected from others; yet, accessible for when I need certain functions or objects. JS patterns are quite opinionated, and their use varies with your needs; so, while there isn’t one particular approach your “should” implement, I find the RMP useful for the following reasons:

  1. It prevents the pollution of the Global Namespace;
  2. It only exposes the variables and functions to the global object that I want it to;
  3. Public functions have access to private variables and methods;
  4. The intention of the code is much clearer and in line with an object oriented programming approach.

Before diving into the RMP, it’s important to mention that you should have a solid understanding of scope, objects, IIFEs, and closures in JS, as the RMP leverages these concepts and features. Next we’ll look at a simple example that goes over these concepts at a high level, but I encourage anyone unfamiliar with this content to read Douglas Crockford’s book, JavaScript: The Good Parts. I’m also a very, VERY big fan of Anthony Alicea’s tutorials on JavaScript (including Angular and Node) and highly recommend watching his lectures.

Scope, IIFEs, and Closure

var hello = "Hello", // Creates a variable "hello" scoped to the global object
world = "World!"; // Creates a variable "world" scoped to the global object

(function closureExample (){

var hello = 'Hola'; // Creates a variable "hello" scoped to the function

!function greet () { // use bang method to convert function statement to a function expression
console.log(hello + " " + world);
}(); // Logs Hola World to the console.
})()

console.log(hello); // "Hello"

In JS, scope is the context in which values and expressions are visible or accessible. In the example above, we declare the variable “hello” twice: once in the global context, and once in closureExample’s context. Once closureExample’s execution context is complete and popped off the execution stack, the variables declared within the function are not accessible to other functions across the application outside of the function’s context, as illustrated on line 19.

The console.log(hello + " " + world); function has neither "hello" nor "location" in its execution context and therefore looks at its outer reference and sees "hello='hola'" in its parent function's scope and then stops going up the scope chain for that variable; however "world='World'" doesn't exist until greet's outer reference points to the global scope. Greet traverses the scope chain twice to find the variables it needs. Notice that greet has access to closureExample's variable "Hello" despite the fact that closureExample has popped off the the execution stack. Closures allow a functions children functions to still point to its variables in memory. Running the application confirms these assertions, as we see below.

example of code

An Example of the Revealing Module Pattern

Now that we’ve covered some of the basics, let’s look at how the RMP can protect our code, and only expose to the global object the methods and variables that we explicitly tell it to. In the following code, we create a globally accessible variable that is set to an IIFE that creates a new execution context to which our variables and functions are scoped. At the very end of this IIFE we return an object that is now exposed to the global object with the public methods we want access to defined as methods on the returned object. I start each module with the “use strict” directive to prevent any of our variables accidentally leaking into the global namespace. 

var lookthinkModule = (function(){
'use strict'
// _a, _privateArray, and _privateMethod are protected from the global scope.
// private variables and functions are prepended with a _ to provide a visual note that they are private.
var _a = 4,
_privateObj = {};

function _privateMethod(){
console.log(_a);
}

// Because of closures, publicMethod will have access to variables declared in its parent function's context.
function publicMethod(){
_privateMethod();
console.log(_privateObj);
}

// Here is a method that updates a private object.
function addToPrivateObj(obj){
_privateObj = obj;
console.log(_privateObj);
}

// By returning the object we expose only the methods that we want and protect the private variables from
// any potential overwrites.
return {
publicMethod: publicMethod,
addToPrivateObj: addToPrivateObj,
}

}())

console.log('-----------------\nPublic Method that calls a private method that logs a private variable:')
lookthinkModule.publicMethod();
console.log('-----------------\nPrivate Object updated by the public method:')
lookthinkModule.addToPrivateObj({first_name: 'Nathan', last_name: 'Minarik', job: {company: 'LookThink', location: 'The District', position: 'Developer'}});
console.log('-----------------\nLookthink Module that is accessible globally:')
console.log(lookthinkModule);
console.log('-----------------\nError when trying to access the private methods from the global object:')
lookthinkModule._privateMethod();

By setting the variable lookthinkModule equal an IIFE that returns an object, we are able to control the exposure of our code. In lines 54 – 61 we make various calls of our object’s methods. Line 60 throws an error because we are trying to call a private method, that the global object doesn’t have access to! Yet, we see that we’re able to update private objects within the IIFE thanks to closure wrapping our methods in the parent function’s scope. This is a really awesome and powerful way to keep your code clean and protected even when you’re no longer on a project. Running the application, we see our expectations confirmed. The methods we want exposed are exposed, and the variables we want to be private are private. 

Final Notes

I find the RMP a very helpful programming pattern to protect my code, while still allowing me to use the methods that I’ll need access to as I need. The RMP is an extension of the overall Module Pattern that I think provides more clarity in the code, and removes the need to reference the object within methods when calling other methods as required in the more generic implementation of the module pattern. The difference is mostly cosmetic, but I also find it a bit clearer and requires less typing. Please feel free to comment on this post with any questions, or ways you’ve utilized various JS patterns in your own professional experience.