JavaScript Module Design Pattern

JavaScript Module pattern provides a way to wrap public, private methods (and variable) into a single entity and exposing only the public members to the world outside of module. This allows faster namespace resolution, avoid collision of the methods/variables with other global APIs since the namespace isn’t populated with all many functions, and obviously provides cleaner code.

Implementing Basic JavaScript Module Pattern

Implementing a module is pretty simple, lets say we need to create a Calculator module.

To do so, we execute a function expression which returns an object containing all the public members as its properties.

CalcModule = (function() { var pub = {}; pub.add = function(a, b) { console.log('in add()', a, b); return a + b; }; pub.sub = function(a, b) { console.log('in sub()', a, b); return a - b; }; return pub; })();
Code language: JavaScript (javascript)

Here we create and execute an anonymous function and assigns the return value of the function to the variable CalcModule. Inside the function, we have created an object ‘pub‘ and then simply add properties to this object which needs to be exposed to outside world (functions ‘add’ and ‘sub’ in our case). Since the function is anonymously executed, any local variables declared inside the function can still be accessed inside the CalcModule but will not be available outside of module.

Now to use this calculator, we can simple write:

CalcModule.add(5,2) //returns : 7 CalcModule.sub(5,2) //returns : 3
Code language: JavaScript (javascript)

Demo

Note that as JavaScript doesn’t provide any access modifiers, the private members inside a module were created using closures. And the module itself was created using anonymous function expression.

Adding private members to Module

Lets give our calculator the ability to store results in its memory. To do so we add a private variable ‘mem‘ and expose a function to retrieve data. Any declared function or variable will be private unless we add it as a property to the returned public object.

CalcModule = (function() { var pub = {}; var mem = new Array(); //private variable var storeInMemory = function(val) { //private function mem.push(val); }; pub.add = function(a, b) { var result = a + b; storeInMemory(result); //call to private function return result; }; pub.sub = function(a, b) { var result = a - b; storeInMemory(result); //call to private function return result; }; pub.retrieveFromMemory = function() { return mem.pop(); }; return pub; })();
Code language: JavaScript (javascript)

Usage:

CalcModule.add(2,10); CalcModule.add(5,15); console.log(CalcModule.retrieveFromMemory()); //outputs 20 console.log(CalcModule.retrieveFromMemory()); //outputs 12
Code language: JavaScript (javascript)

Demo

Importing Parameters in JavaScript Module

Once the basic module is ready, we can pass parameters in the module during its initialisation (effectively importing them inside the module). For eg, we would like to pass jQuery variable into our module so that resolving jQuery variable inside of module don’t have to search entire scope chain but is available locally. To do so we simply pass the ‘jQuery’ in the parenthesis used to execute the function expression. In this example, we use jQuery’s isNumeric() function to check whether input provided is a number.

CalcModule = (function($) { var pub = {}; var INVALID = 'invalid input'; pub.add = function(a, b) { if ($.isNumeric(a) && $.isNumeric(b)) { return a + b; } else { return INVALID; } }; pub.sub = function(a, b) { if ($.isNumeric(a) && $.isNumeric(b)) { return a - b; } else { return INVALID; } }; return pub; })(jQuery); //passed 'jQuery' global variable into local parameter '$'
Code language: JavaScript (javascript)

Demo

Separating Module across different JS files: Augmentation

Let say, due to overly complex module we want our module to be defined in different js files. And that too in a way so that the implementation is independent of the order of execution of js files (It might happen that one JS file gets loaded before another). In our example lets separate out ‘add’ and ‘sub’ functions into one js-file, and memory implementation into another file.

File: calc.js

var CalcModule = (function($, pub) { //jQuery will still be available via $ var mem = new Array(); //private variable pub.storeInMemory = function(val) { mem.push(val); }; pub.retrieveFromMemory = function() { return mem.pop(); }; return pub; })(jQuery, CalcModule || {});
Code language: JavaScript (javascript)

File: calc_functions.js

var CalcModule = (function($, pub) { //jQuery will still be available via $ pub.add = function(a, b) { var result = a + b; pub.storeInMemory(result); return result; }; pub.sub = function(a, b) { var result = a - b; pub.storeInMemory(result); return result; }; return pub; }(jQuery, CalcModule || {}));
Code language: JavaScript (javascript)

First things to notice in above code is passing of parameters into the module. We pass the same javascript module ‘CalcModule’ as argument into the anonymous function and which gets assigned to parameter ‘pub’. Inside the function, we add properties to this parameter ‘pub’, and then return the same variable which gets assigned back to CalcModule. Thus, we managed to extend the existing CalcModule with new properties.

Second thing to notice is the OR ( || ) condition in the call. This is what makes above files independent of each other with respect to order of execution. If the CalcModule doesn’t exists yet, a new object is created (using ‘{}’) and passed to the parameter ‘pub’ which is then assigned to CalcModule. This ability to allow loading of scripts in any order, converts a Strict Augmentation to Loosely Augmentation.

This functionality to extend the module with other members is called Augmentation. And if the order in which these modules are loaded is defined than its called a Strict Augmentation, or else if the order is not important as in example above, it is called Loose Augmentation.

A disadvantage of separating same module across different files is inability to share private variables between files. Above logic worked because we can pass the global variable CalcModule to different anonymous functions and add properties to it, but since CalcModule only exposes public APIs, different modules won’t be able share private members (remember private members are implemented using closures, and each anonymous function will have its own closure).

Revealing Module Pattern

A variation of the module pattern is the Revealing Module Pattern. As described earlier, for creation of a module it is required to return an object form anonymous function which has all the public properties. So lets change the implementation of the second example as below:

CalcModule = (function() { var mem = new Array(); //private variable var storeInMemory = function(val) { //private function mem.push(val); }; var add = function(a, b) { var result = a + b; storeInMemory(result); //call to private function return result; }; var sub = function(a, b) { var result = a - b; storeInMemory(result); //call to private function return result; }; var retrieveFromMemory = function() { return mem.pop(); }; return { add: add, sub: sub, popMemory: retrieveFromMemory }; })();
Code language: JavaScript (javascript)

Notice the changes here, we are not creating a separate ‘pub’ variable and then adding properties to it. But instead we define all the functions public or not in the same way, and then in the return statement create a new object and add properties to it.

Advantages of Revealing Module pattern

  1. Consistent coding style inside the module for both private and public members.
  2. Better control on the name of the public API, i.e., if it is required to change the name of add() method to addition(), all we need to do is change the name in the return statement without effecting the function name inside the module.
  3. Control on what to make public, just adding/removing the properties in return statement is sufficient.
  4. As always, cleaner code.

This concluded the basics of module design pattern.

View Comments

Share
Published by
Aditya Jain
Tags: design patterns JavaScript

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

4 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

4 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

4 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

4 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

4 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

5 years ago