Introduction
In this article, I'll be explaining one of the popular design patterns used in JavaScript called "Revealing Module Pattern". As it is a JavaScript design pattern, the only pre-requisite is basic knowledge of JavaScript. Along the way, I'll also explain some basic JavaScript constructs which will help us write JavaScript in an Object Oriented approach. I'll also be explaining another concept called IIFE (Immediately Invoked Function Expression).
Let's Get Started
Here, we are talking about design patterns and obviously Object Oriented Programming comes into the picture when we talk about design patterns. So you must be thinking we have to write a class, create objects, encapsulate/abstract members, etc. But in JavaScript, we can't create a class like we do in other Object Oriented Programming languages C++/C#, etc. However don't worry, we'll see later how to simulate classes in JavaScript. Let's get some JavaScript concepts cleared before we go further into creating classes.
Objects
In JavaScript, everything is an object with the exception of number, string, boolean, null and undefined. JavaScript objects are similar to dictionaries with key/value pairs.
Object Literal Notation
The object literal notation is used to denote objects in JavaScript.
Example: Here, we define an employee
object named employeeObj
with 3 properties - firstName
, lastName
and age
.
var employeeObj = {
firstName : "Robert",
lastName : "Bosch",
age : 31
};
We can also create objects by creating an instance of the Object
type. We can also start adding properties in the object directly.
var obj = new Object();
obj.firstName = "John";
obj.lastName = "Bosch";
Functions and Scope
If we define a variable which is not inside any function, then that variable would be called a global variable. And defining a variable within a function would be local to that function and so the scope of the local variable would be within the function.
In the example below, "a
" is a global variable and so it is accessible within the function AddMe
and from outside too. "b
" again is a local variable to the function AddMe
so won't be accessible outside of the function AddMe
. This is a very important concept which leads us to another concept called closure which we explain below.
var a = 27;
function AddMe(valueToAdd){
var b = 100;
return a + b + valueToAdd;
}
document.writeln(AddMe(50));
Closure
JavaScript allows writing nested functions, i.e., function within a function and so on. And the inner functions can access variables defined outside the inner function and this concept is called a Closure. Closure is a computer programming term and for those interested to know more about it, you can read from the link below:
So in the example below, the addinner
function using the variables a
and b
defined outside it creates a closure so that those variables stay beyond there scope. What is important here to notice is that a call to addouter()
function returns a variable which we call later but still the values of the variables "a
" and "b
" are hanging around. Think about it this way, the variable result is nothing but the function addinner
. Now in the last line, we did invoke the result()
function which means we invoked the addinner
function which was able to return the values of "a
" and "b
" variables and it's because of the closure in which it's enclosed.
The concept of closure is a bit difficult to understand if you are reading about it for the first time. Let me give you another reference to understand closure better:
var a = 10;
var addouter = function(){
var b = 20;
var addinner = function(){
return (a + b);
}
return addinner;
}
var result = addouter();
document.writeln(result());
Revealing Module Pattern
So now, we'll use the concepts explained earlier to write a design pattern which is called Revealing Module Pattern.
In the example below, we define an outer function named "Mathlibrary
" which will simulate a class in an Object Oriented language. Inside this class Mathlibrary
, we'll have certain local variables like count
, _add
and _sub
.
count
is a local variable which is used as a counter.
_add
and _sub
variables are functions but as these are local variables, we can treat them as private
methods.
So the variables count
, _add
and _sub
would not be accessible from outside the function Mathlibrary
so that means we have encapsulated them inside the class Mathlibrary
.
Now what does the Mathlibrary
function (representation of a class) return?
As we can see, it returns a JavaScript object in the form of an object literal.
And what does the returned object contain?
It contains 2 properties, "add
" and "sub
". "add
" points to nothing other than the _add
variable which is a function to add 2 numbers and also display a counter. Similarly, "sub
" points to _sub
variable which is a function to subtract 2 numbers and display a counter.
After we defined the function(class) Mathlibrary
, we created an instance of it named "mathObj
" and later called the 2 public
methods, add()
and sub()
.
So in essence, we created a class with 1 private
variable, 2 private
methods and 2 public
methods. This particular pattern is called the "Revealing Module Pattern".
var Mathlibrary = function(){
var count = 0;
var _add = function(a, b){
count++;
document.writeln(a + b + "- count = " + count);
};
var _sub = function(a, b){
count++;
document.writeln(a - b + "- count = " + count);
}
return{
add : _add,
sub : _sub
}
}
var mathObj = new Mathlibrary();
mathObj.add(150, 100);
mathObj.sub(150, 100);
Singleton
With the above pattern, we simulated creating a normal class where every time, we new up an object an instance got created. In the below sample, I'll modify the code slightly to create a singleton so that there will be a single instance of the object in memory.
The change done is actually very simple. We have just added a parenthesis()
with a semicolon to the function definition of Mathlibrary
which will self execute. And as it's self executing, we don't have to new it up and call the methods on it.
var Mathlibrary = function(){
var count = 0;
var _add = function(a, b){
count++;
document.writeln(a + b + "- count = " + count);
};
var _sub = function(a, b){
count++;
document.writeln(a - b + "- count = " + count);
}
return{
add : _add,
sub : _sub
}
}();
Mathlibrary.add(150,100);
Mathlibrary.sub(150,100);
IIFE (Immediately Invoked Function Expression)
We already read about global variables and if we have a look at the above 2 programs that we wrote, we will see that we created a couple of global variables, one for creating the class Mathlibrary
and one for creating the instance of the class mathObj
. And let me tell you something that you already know, global variables are bad. Yes in JavaScript, it's even worse. Read http://www.oreillynet.com/pub/a/javascript/excerpts/javascript-good-parts/awful-parts.html.
So to avoid global variables, we'll create an IIFE, where we'll wrap the entire code of the Revealing Module Pattern in an anonymous function (a function with no name) and add parenthesis at the end to self execute it (similar to the singleton pattern). And that's it, we have a design pattern with encapsulated members and no global variables.
(function(){
var Mathlibrary = function(){
var count = 0;
var _add = function(a, b){
count++;
document.writeln(a + b + "- count = " + count);
};
var _sub = function(a, b){
count++;
document.writeln(a - b + "- count = " + count);
}
return{
add : _add,
sub : _sub
}
}
var mathObj = new Mathlibrary();
mathObj.add(150, 100);
mathObj.sub(150, 100);
}());
Summary
In this article, we learned one of the very popular design patterns used in JavaScript - the "Revealing Module Pattern".
If you have any questions, please post them below and I'll try my best to answer them. Hope it helps!
History
- 21st September, 2014: Initial version