The “Module” pattern is based on closures and consists of two components: an outer function that defines a lexical environment, and a return set of inner functions that have access to this environment.
Let’s define the simplest module:
let foo = (function(){
let obj = {greeting: "hello"};
return {
display: function(){
console.log(obj.greeting);
}
}
})();
foo.display(); // hello
The variable foo is defined here, which represents the result of the anonymous function. Inside such a function, an obj object is defined with some data.
The anonymous function itself returns an object that defines the display function. The returned object defines a public API through which we can access the data defined within the module.
return {
display: function(){
console.log(obj.greeting);
}
}
This design allows you to close a certain set of data within the module function and mediate access to them through a specific API – returned internal functions.
Let’s look at a slightly more complex example:
let calculator = (function(){
let data = {number: 0};
return {
sum: function(n){
data.number += n;
},
subtract: function(n){
data.number -= n;
},
display: function(){
console.log("Result: ", data.number);
}
}
})();
calculator.sum(10);
calculator.sum(3);
calculator.display(); // result: 13
calculator.subtract(4);
calculator.display(); // result: 9
This module is a primitive calculator that performs three operations: addition, subtraction, and output.
All data is encapsulated in a data object that stores the result of the operation. All operations are represented by three return functions: sum, subtract and display. Through these functions, we can control the result of the calculator from the outside.