Module Design Pattern
Structural: Module Pattern
What is the Module Design Pattern in JavaScript?
View Answer:
//*******************************************************//
// The Module Pattern
//*******************************************************//
// ES2015+ keywords used: import, export, let, const
let counter = 0;
const testModule = {
incrementCounter() {
return counter++;
},
resetCounter() {
console.log(`counter value prior to reset: ${counter}`);
counter = 0;
},
};
// Default export module, without name
export default testModule;
// Usage:
// Import module from path
import testModule from './testModule';
// Increment our counter
testModule.incrementCounter();
// Check the counter value and reset
// Outputs: counter value prior to reset: 1
testModule.resetCounter();
Why is the Module Pattern used?
View Answer:
The Module pattern belongs to which design pattern family?
View Answer:
What is a good use case for the Module Design Pattern?
View Answer:
What are some of the advantages of employing the Module pattern?
View Answer:
What are some of the disadvantages of employing the Module pattern?
View Answer:
Are there any alternatives to using the Module Pattern?
View Answer:
What are public and private methods in the context of the Module Pattern?
View Answer:
var myModule = (function () {
var privateVariable = 'private';
var privateMethod = function() {
console.log('Accessed private method');
return privateVariable;
};
return {
publicMethod: function() {
console.log('Accessed public method');
return privateMethod();
}
};
})();
console.log(myModule.publicMethod()); // Logs: 'Accessed public method', 'Accessed private method', and then returns 'private'
console.log(myModule.privateMethod); // Logs: undefined, because it's private and not accessible directly
console.log(myModule.privateVariable); // Logs: undefined, because it's private and not accessible directly
In this pattern, only the properties and methods that are returned from the anonymous function are available publicly. Everything else within the function remains private.
Notice the use of an IIFE (Immediately Invoked Function Expression), (function () { /* code */ })()
. This technique is used to create a new scope that is immediately executed and does not pollute the global namespace. Anything defined inside this function is in its own private scope and can't be accessed from the outside, unless explicitly exposed (like publicMethod
in our example).
Although, we can use an IIFE (Immediately Invoked Function Expression), in Modern JavaScript using JS Modules is the recommended approach. Modern ECMAScript (ES6 and onwards) introduced a native module system that inherently uses the module design pattern.
How does the Module Pattern help in reducing global scope pollution?
View Answer:
Although, we can use an IIFE (Immediately Invoked Function Expression), in Modern JavaScript using JS Modules is the recommended approach. Modern ECMAScript (ES6 and onwards) introduced a native module system that inherently uses the module design pattern.
How does the Revealing Module Pattern relate to the Module Design Pattern?
View Answer:
Can modules communicate with each other in the Module Pattern?
View Answer:
How does the Module Pattern support code reusability?
View Answer:
How can the Module Pattern help improve code maintainability?
View Answer:
What Modern ECMAScript feature uses the Module Design Pattern?
View Answer:
Here is an example of how to define and use modules using export
and import
.
Consider a file mathModule.js
:
// mathModule.js
export function add(x, y) {
return x + y;
}
export function subtract(x, y) {
return x - y;
}
var pi = 3.141592653589793;
export { pi };
And then, in another file app.js
, you can import these exported methods and variables:
// app.js
import { add, subtract, pi } from './mathModule.js';
console.log(add(2, 3)); // Outputs: 5
console.log(subtract(5, 2)); // Outputs: 3
console.log(pi); // Outputs: 3.141592653589793
In the example above, add
, subtract
, and pi
are encapsulated within mathModule.js
and can be imported in other JS files using the import
statement.
You can also import all exported members at once using the *
operator:
// app.js
import * as math from './mathModule.js';
console.log(math.add(2, 3)); // Outputs: 5
console.log(math.subtract(5, 2)); // Outputs: 3
console.log(math.pi); // Outputs: 3.141592653589793
With this syntax, you get an object math
that contains all the exported members from mathModule.js
.
Native ES6 modules are static, meaning you can't conditionally import or export modules. They are also subject to CORS and can be used in browsers with the type="module"
attribute on a script
tag. Node.js also supports ES modules, but the implementation may be different from browsers.