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.