example_1.js : When invoked with the require command this module will return a simple function that takes two parameters a,b, and adds them together with internal variable c.
example_2.js : When invoked with the require command this module will return a constructor function Fn() . Constructor functions are templates that can be used to create new objects with the new command. In this case the objects created by the constructor will have one property c which is set to 6, and one method add(a,b) which when called adds the parameters a+b with the objects property c.
example_3.js : This module is almost identical to example_2.js but instead of exposing a constructor function it uses the constructor function to create an object with the new command and assigned this object to the module.exports parameter. .
main.js : This is our node.js application that is executed with the command node main.js. It shows how each of the modules is first loaded with the require() function and assigned to a variable addA, addB and addC. Thus addA is assigned to the function exposed from example_1.js, addB is assigned to the constructor function exposed from example_2.js and addC is assigned to the object exposed from the example_3.js module. The remaining code in main.js shows how the functionlaity of addA, addB and addC are called with the result returned by the function/method stored in variable result.
Singleton Design Pattern
It is important to understand that when you first use the require() function to load a module it actually caches whatever is assigned to the module’s module.export parameter into memory, then assigns it to the variable. If any other modules in your node.js application try to load the same module with a require command then what is returned is actually the previously cached code. Lets consider how this impacts our example_3.js module. The first use of require() will create and load an object into the require cache. If any other modules in your application also includes the command require(‘./myModules/example_3.js’), they will not create a new object, but instead they will get a reference to to the object that is already in your applications require cache. This is called a singleton pattern, as there will only ever be one object created in your application from the example_3.js module, no matter how many times you load the module with the require command. Singleton patterns are excellent for managing data in an application access across multiple modules. The diagram below is an example of this approach.
appData.js returns an object that has one parameter (counter) and two methods (set and get). The first line of our main.js application loads this module, thus creating the object holding our counter parameter in our applications require cache.
increment.js is a simple function that increments the counter parameter in the appData.js module. Because our main.js application already loaded appData.js in line 1, the increment.js module will not reload appData.js but simply assign the data variable to point to the object in the require cache. i.e. the singleton pattern creates one object in our cache allowing access to the counter parameter for any module that loads the appData.js module.
(Note the difference in how the path to the appData.js module is different for main.js and increment.js. The path name needs to be relative to file that the require is called from. From main.js the path is ‘./myModules/appData.js’, from increment.js the path is ‘./appData.js’.)