Module Pattern and Revealing Module Pattern in JavaScript
Modular thinking is one of the cornerstones of modern JavaScript programming. The Module Pattern and Revealing Module Pattern allow writing clean, encapsulated, and controlled code without polluting the global namespace.
Before the advent of ES6 modules, IIFEs (Immediately Invoked Function Expressions) were the primary way to create modules in JavaScript.
Module Pattern
It uses IIFE to create a private scope where we can define private and public members.
const CounterModule = (function () { // private members let count = 0;
function increment() { count++; }
function getCount() { return count; }
// public API return { increment, getCount }; })();
CounterModule.increment();
console.log(CounterModule.getCount()); // 1 console.log(CounterModule.count); // undefined (private)
Key features:
- Private data is kept in a closed scope
- Only public API is exposed to the outside world
Revealing Module Pattern
This is a simplified and more readable version of the Module Pattern. All functions and variables are declared in the private scope, and then only what we want to expose is returned using an object with the same names.
const MathModule = (function () { let PI = 3.14159;
function area(radius) { return PI * radius * radius; }
function circumference(radius) { return 2 * PI * radius; }
return { area, circumference }; })();
console.log(MathModule.area(2)); // 12.56636 console.log(MathModule.PI); // undefined
Expressed advantages:
- Code structure is simpler and more readable
- It's clear what's accessible to the outside world
Complex Example: Dependency Injection with Reveal Pattern
By including dependencies in the module, we can achieve a more modular and testable system.
const Logger = (function () { function log(message) { console.log(`[LOG]: ${message}`); }
return { log }; })();
const UserService = (function (logger) { let users = [];
function addUser(user) { users.push(user); logger.log(User ${user} added); }
function getUsers() { return users; }
return { addUser, getUsers }; })(Logger);
UserService.addUser('Anna'); console.log(UserService.getUsers());
Results:
- Modules are separated from each other - loose coupling
- We can replace
Loggerwith a mock version during testing
Conclusion
The Module Pattern and Revealing Module Pattern in JavaScript allow elegant management of private/public separation and building encapsulated modules. Although ES6 modules are now more widely accepted, these approaches are still useful for closures and encapsulation, especially when writing libraries.
In the next part, we'll examine ES6 classes and modules with modern OOP applications in JavaScript.