Module Pattern in JavaScript in Depth
Here I have covered the Module Pattern in JavaScript.
What is Module Pattern?
Modules are an integral part of any robust application's architecture and typically help in keeping the units of code for a project both cleanly separated and organized. The module pattern is a common JavaScript coding pattern. To understand Module Pattern you should have knowledge about the Closure principle of JavaScript.
What is Closure?
Closures are a means through which inner functions can refer to variables present in their outer enclosing function after their parent functions have already terminated. Here is an example for Closure:
// A function that generates a new function for adding numbers
function addGenerator(num) {
// Return a simple function for adding two numbers
// with the first number borrowed from the generator
return function (toAdd) {
return num + toAdd
};
}
// addFive now contains a function that takes one argument,
// adds five to it, and returns the resulting number
var addFive = addGenerator(5);
// We can see here that the result of the addFive function is 9,
// when passed an argument of 4
alert(addFive(4) == 9); // Which return true
Example of Module Pattern
var EmployeeModule = (function () {
var employeeList = [];
return {
add: function (employee) {
employeeList.push(employee);
},
getAll: function () {
return employeeList;
},
totalCount: function () {
return employeeList.length;
}
};
})();
We can use our EmployeeModule
in this way.
EmployeeModule.add({ Id: '01', Name: 'Emon Khan', Designation: 'Software Engineer' });
EmployeeModule.add({ Id: '02', Name:'Khairul Islam', Designation: 'Senior Software Engineer'});
EmployeeModule.getAll();
Module Pattern Variations
The Revealing Module Pattern
The Revealing Module pattern came from the fact that we need to repeat the name of the main object when we want to call a public method from another or access public variables. Another problem is, if the Module code is too large it is difficult to see which methods or variables are public and which are not. As a result an updated pattern comes into play where we would simply define all of our functions and variables in private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.
An example of creating the Revealing Module pattern:
var EmployeeModule = (function () {
var employeeList = [];
var allEmployee = function () {
return employeeList;
};
var add = function (employee) {
employeeList.push(employee);
};
var totalCount = function() {
return employeeList.length;
};
return {
add: add,
getAll: allEmployee,
totalCount: totalCount
};
} ());
Advantages
This syntax of pattern is more consistent and more clear at the end of the module where our functions and variables may be accessed publicly.
Disadvantages
A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.
As a result of this, modules created with the Revealing Module pattern may be more fragile than those created with the original Module pattern, so care should be taken during usage.
Notes
If your Module does not require any overridden functionality then this approach is perfect for your application.
Extending Module Pattern
This is one of the powerful features of the Module pattern. For a large application different developers can work on different functionally on the same Module by extending the Module.
An example of extending the Module Pattern where the var
statement is not necessary:
var EmployeeModule = (function (my) {
my.anotherFunction = function () {
return alert('this is another function.');
};
} (EmployeeModule));
Loose Augmentation in Module Pattern
While our example above requires our initial module creation to be first, and the augmentation to happen second, that isn't always necessary. One of the best things a JavaScript application can do for performance is to load scripts asynchronously. We can create flexible multi-part modules that can load themselves in any order with loose augmentation. Each file should have the following structure:
var EmployeeModule = (function (my) {
// add functionality...
return my;
}(EmployeeModule || {}));
In this pattern, the var
statement is always necessary.
Tight Augmentation in Module Pattern
While loose augmentation is great, it has some limitations. We cannot override module properties safely. We also cannot use module properties from other files during initialization (but we can at run-time after initialization). Tight augmentation implies a set loading order, but allows overrides. Here is a simple example:
var EmployeeModule = (function (my) {
my.add = function () {
//override the method.
};
return my;
}(EmployeeModule));
Global Import in Module Pattern
We can also import other JavaScript libraries in our Module.
(function ($, Y) {
// now have access to globals jQuery (as $) and YAHOO (as Y) in this code
}(jQuery, YAHOO));
Sub-modules in Module Pattern
There are many cases where we can create sub-modules. It is just like creating a regular module.
EmployeeModule.subModule = (function () {
var my = {};
// ...
return my;
}());
Points of Interest
From my little experience I understood one thing, we can not only follow a design pattern in server side coding but also in client side scripting. Module pattern is one of the best patterns for client-side scripting. It makes our client scripting more clear, consistent, understandable, and maintainable.