Introduction
In this article, we will look at two popular JavaScript patterns, the module, and revealing module patterns.
Module Pattern
To understand the module pattern, it is necessary to first understand what an IIFE (Immediately Invoking Function Expression) is. I will recommend you read about that first over here before proceeding further.
Now that we have the fundamentals of IIFE in place, let us look take a step-by-step approach to create a module pattern.
Step 1:
We will first create an IIFE and assign it to the constant module. When you run the below code, the output will be "The initial value of Person Object is {"name": "Skay", "age":38}".
The IIFE contains a private 'person' object and a private function 'addProperty' that accepts a property name and a property value.
Two things to note at this stage:
- If you console.log(module), then you'll get 'undefined' since nothing is returned by this function.
- The function 'addProperty' has not be invoked while running the IIFE and hence the console.log statement inside the function will not run.
const module = (function() {
//private variable
const person = {
name: 'Skay',
age: 38
}
//private function
function addProperty(propName, propValue) {
person[propName] = propValue;
//Displays the value of person object after a new property has been added
console.log(`The Person object after addProperty function is executed is ${JSON.stringify(person)}`);
}
//Displays the initial value of the person object
console.log(`The Initial value of Person object is ${JSON.stringify(person)}`);
}());
Step 2:
In this step, we will do the following things:
- Return a public method 'callAddPropertyFn' from the IIFE. The method will be returned to the 'module' variable. You can verify it by adding a console.log(module) outside the IIFE. You should get an output like this "{callAddPropertyFn : fn}".
- Since the function 'callAddPropertyFn' is inside the IIFE, it has access to all private variables and functions.
- You can invoke the function 'callAddPrpertyFn' from outside the IIFE function as shown below.
The output when you run the below code:
"The Initial value of Person object is {"name":"Skay","age":38}"
"The Person object after addProperty function is executed is {"name":"Skay","age":38,"gender":"Male"}"
const module = (function() {
//private variable
const person = {
name: 'Skay',
age: 38
}
//private function
function addProperty(propName, propValue) {
person[propName] = propValue;
//Displays the value of person object after a new property has been added
console.log(`The Person object after addProperty function is executed is ${JSON.stringify(person)}`);
}
//Displays the initial value of the person object
console.log(`The Initial value of Person object is ${JSON.stringify(person)}`);
//You can return a variable or function that the outside world will have access to
return {
callAddPropertyFn: function(propName, propValue) {
//call the private function addProperty
addProperty(propName, propValue);
}
}
}());
//You can invoke the callAddPropertyFn since it's returned by the IIFE
module.callAddPropertyFn('gender', 'Male');
That's it! Now you know how to define a module pattern. Basically, we've created a module that's accessible globally while protecting the private members and functions.
Usually, object-oriented languages such as Java provide 'private' and 'public' access modifiers within a Class, which provide us a way to protect what we want to by using the keyword 'private'.
Unfortunately in JavaScript, the default access level is global and care should be taken to protect the variables and functions that you do not want to expose and Module pattern does exactly that for you.
Revealing Module Pattern
Revealing module pattern is exactly like module pattern but with a small twist. Let us take the above example and add another method 'removeProperty' to the IIFE.
const module = (function() {
//private variable
const person = {
name: 'Skay',
age: 38
}
//private function - addProperty
function addProperty(propName, propValue) {
person[propName] = propValue;
console.log(`The Person object after addProperty function is executed is ${JSON.stringify(person)}`);
}
function removeProperty(propName) {
delete person[propName];
console.log(`The Person object after removeProperty function is executed is ${JSON.stringify(person)}`);
}
function displayPerson() {
console.log(`The value of Person object is ${JSON.stringify(person)}`);
}
return {
addProperty: addProperty,
removeProperty: removeProperty,
displayPerson: displayPerson
}
}());
module.displayPerson();
module.addProperty('gender', 'Male');
module.removeProperty('age');
If you look at the return statement, the values of variables and functions can be returned in a conventional JavaScript way. We are using the addProperty, removeProperty and displayPerson as pointers to the private functions.
This is a very clean way of specifying the public members and functions that you want to define to the outside world. The biggest advantage of revealing module pattern as compared to module pattern is that it improves code readability significantly.
Revealing module pattern is used to provide abstraction over private implementations by providing public APIs.
Conclusion
Both module and revealing module patterns should be used to protect variables and functions that you do not wish to share with the outside world. I would favour revealing module pattern for it's neater way of defining public APIs and improving code readability.
Hope you enjoyed this article. Please share your comments and don't forget to share it with your friends, co-workers whomever you think this will benefit.
You might also be interested in:
Top comments (2)
Thank you for this post! It's has praticulary value. I will try incorporate this patterns in my project on JS-vanilla.
I'm glad you found it useful! Good luck with the implementation..