A key attribute of modules is encapsulation. The objects that are not exported from the module are private to the module, and cannot be accessed from code outside the module. To reiterate, modules are treated as if they were written as follows:
(function() { ... contents of module file ... })();
This JavaScript idiom defines an anonymous private scope. Anything declared within that scope cannot be accessed by code outside the scope. That is, unless some code makes object references available to other code outside this private scope. That's what the module.exports object does: it is a mechanism for the module author to expose object references from the module. Other code can then access resources inside the module in a controlled fashion.
The top-level variables inside a module look like they exist in the global scope. Instead of being truly Global, they're safely private to the module and are completely inaccessible to other code.
Let's take a look at a practical demonstration of that encapsulation. Create a file namedmodule1.js, containing the following:
const A = "value A"; const B = "value B"; exports.values = function() { return { A: A, B: B }; }
Then, create a file namedmodule2.js, containing the following:
const util = require('util'); const A = "a different value A"; const B = "a different value B"; const m1 = require('./module1'); console.log(`A=${A} B=${B} values=${util.inspect(m1.values())}`); console.log(`${m1.A} ${m1.B}`); const vals = m1.values(); vals.B = "something completely different"; console.log(util.inspect(vals)); console.log(util.inspect(m1.values()));
Then, run it as follows (you must have Node.js already installed):
$ node module2.js A=a different value A B=a different value B values={ A: 'value A', B: 'value B' } undefined undefined { A: 'value A', B: 'something completely different' } { A: 'value A', B: 'value B' }
This artificial example demonstrates encapsulation of the values inmodule1.jsfrom those inmodule2.js. The A and B values inmodule1.jsdon't overwrite A and B inmodule2.jsbecause they're encapsulated withinmodule1.js. The valuesfunction inmodule1.js does allow code in module2.js access to the values; however, module2.js cannot directly access those values. We can modify the object module2.js received from module1.js. But doing so does not change the values within module1.js.