JavaScript Revealing Module Pattern

JavaScript has gotten very popular lately with the right rich web client applications. There a many JavaScript libraries available, both open source and commercial with very strong support from the community. However, as JavaScript application grows in size, it is very easy for the code to get messy and out of control. If care and consideration are not kept in mind as new features are added, it is easy to run into all sorts of variable collisions and other scope issues. Third party libraries such as RequireJS were introduced to help keep JavaScript code modular. However, there are several techniques that were developed over the years that are essential for maintaining scalable and modular JavaScript code. I am discussing one of these techniques below and it is know as the Revealing Module Patter.

The Revealing Module Pattern
This popular pattern focuses on wrapping pieces of JavaScript functionalities into stand alone reusable modules. The pattern relies on the powerful JavaScript support with closures, local variable scope in functions and even the prototype construct in JavaScript.

The overall generic structure of the pattern looks like the following:

var ModuleName = function(param1, param2, ...) {
// Local variables and functions are declared below
// Use var as opposed to 'this' to ensure local scope
return {
// All public members and functions are revealed in this returned object
};
};

Consequences

  • The module name follows Pascal-Case by convention. Even though this is not enforced by JavaScript, it is important to indicate that this is a declaration of a module that requires instantiation.
  • The chance for variable name collision is minimized. With all the local variables and functions declared using the var keyword, their scope will be private to the module.
  • The object returned by the module declaration contains references to the private functions and members that we want to reveal or expose to outer scopes. JavaScript creates closures around these private elements and makes them available publicly.

Example:

var Employee = function(id) {
// Private Member
var empControl = document.getElementById(id);
// Private Function
function doAssignName(firstName, lastName) {
empControl.innerHTML = lastName + ', ' + firstName;
}
return {
// Reveal Public Members
assignEmployeeName: doAssignName
}
}

In the example above, the only public member revealed by the Employee module is the function ‘assignEmployeeName’. This function creates a closure to the internal ‘doAssignName’ and therefore it has access to it. Note that the name exposed publicly and the private function name can be the same. In fact, that is the convention widely used. I used different names in this example for the sake of demonstration only.

To assign an employee a name using the module above, we make an instance of the Employee module and then invoke the ‘assignEmployeeName’.

var employee = new Employee(123);
employee.assignEmployeeName('Carson', 'Bill');

Using Revealed Modules as Singletons
By invoking the module declaration function with parameters immediately, an single instance of the module is created immediately and the module can no longer be instantiated. This results in a singleton object that is used by the application. This might be useful if there is no desire to created multiple instances of an object an the module contained only extrinsic state data.

Example:

// lower case for the first letter in module name
var employee = function(id) {
var empControl = document.getElementById(id);
function doAssignName(firstName, lastName) {
empControl.innerHTML = lastName + ', ' + firstName;
}
return {
assignEmployeeName: doAssignName
}
}(123) // Immediately invoked with id 123
// No need to call the employee module when calling a function
employee.assignEmployeeName('Carson', 'Bill');

Using the Prototype in Revealing Module Pattern
In the example above, all the logic specific to employees is encapsulated in a module called the Employee module. Any necessary number of modules can be added to the application without any risk or variable scope collision. However, there is an issue with the module declared above. The private function ‘doAssignName’ is created directly in the module. What this means is that for every instance of the Employee that is created, a fresh copy of the function body is created on the instance itself. This sounds like a lot of code duplication.

In order to maintain a single copy of each function declared that is shared across all created instances, the function should be added directly in the function’s prototype. To place function declaration on the module’s prototype, a separate call is needed to assign all functions to the prototype.

All the module ‘intrinsic state’ data goes in the module body declaration. This is the data specific to the instance that is instantiated from the module.

All the module ‘extrinsic state’ data goes in the prototype declaration. This is the data that is going to be shared by all the instances. This is similar to the static contents in a C# or a Java class.

Example:

var Employee = function(id) {
// Intrinsic State
// Use the 'this' keyword
// This ensures variables are accessible by the prototype
this.empControl = document.getElementById(id);
};
Employee.prototype = function() {
// Extrinsic State
function doAssignName(firstName, lastName) {
// Use the 'this' keyword to access intrinsic data
this.empControl.innerHTML = lastName + ', ' + firstName;
}
return {
assignEmployeeName: doAssignName
}
}() // Add parenthesis

The last pair of parenthesis added to the prototype declaration ensures the immediate invocation of the function. This way, the ‘revealed’ object that is returned is assigned to the prototype. Failure to do so assigned the body of the function to the prototype as opposed to the revealed object, which leads to bad results.

Invoking the module above is no different than before. However, it should be more efficient now that the function is added on the prototype.

A Word of Caution when using the ‘this’ Keyword
Unlike C# and Java, the ‘this’ keyword in JavaScript varies by the context of the function. It always refers to the function that ‘called’ the current function. So, if a function within the prototype calls a second function that utilizes the ‘this’ keyword, the context in which the second function is invoked at suddenly changes. There many solutions to this common JavaScript problem out there including passing the context as a parameter to the second function. Also, some libraries use the concept of ‘binding’.

An enthusiastic architect and full-stack developer with many years working with enterprise software and cloud services in multiple domains.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store