JavaScript has no concept of scope (local) and namespace, and JavaScript is a scripting (interpretive) language. When the js engine parses it, it starts interpreting it "together" from top to bottom (generating ast, then byte code, and finally machine code). This causes an obvious problem when interpreting: symbol overhead, "In compiled languages, symbol conflicts are symbolic conflicts. Symbol conflicts are errors at compile time. symbol overhead does not have any error hints and can be interpreted and executed normally, which is obviously unacceptable."
Therefore, the modularization of JavaScript is very necessary in engineering practice.
In a JS world without modularity:
//index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>demo</title> <script src="alex.js" type="text/javascript"></script> <script src="lib.js" type="text/javascript"></script> </head> <body> </body> </html>
//lib.js let value = 'value'
//bob.js alert(value)
Bob. Obviously, there is no variable value defined in js, but it will output the variable value normally because of index. Alex is loaded first in html. Bob loaded after JS file. JS files, because JS does not have the concept of namespace, can output normally (equivalent to having all JS files in one file).
Obviously, this does not allow normal encoding to unfold, and individual files (modules) cannot be effectively isolated (all contaminated by variables)
(So all sorts of Sao operations come...)
//lib.js let mod = (function () { let mod = {} mod.value = 'value' mod.say_sm = function(){ alert('say sm') } return mod })()
//bob.js alert(mod.value) mod.say_sm()
Normal Output value and say sm
Direct at lib.js returns an object mod,JavaScript has a function scope, so by calling the function immediately, an object is returned so that other js files can use the object directly. (Variables and functions can be defined inside this immediate call function and given directly to this mod object), which is a compromise and does not essentially avoid variable contamination (mod may contaminate the same variable mod in other js files), and there is a sequential dependency in the html file (the dependent file must be loaded first). This is in the case of a large number of js files...
JavaScript did not support modularization until 2015, and did not support it at the language level until the ES6 standard, where industry specifications were typically developed to "implement" (simulate) modularization.
- Modular specification
- Language support
The industry's popular specification is CommonJS, which has been implemented in full universality.
ES6 support for modularization
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>demo</title> <script src="lib.js" type="module"></script> <script src="bob.js" type="module"></script> </head> <body> </body> </html>
//lib.js let value = 'value' function say_sm(){ alert('say sm') } export{ value, say_sm }
//bob.js import {value,say_sm} from './module/lib04.js' alert(value) say_sm()
As shown above, ES6 introduces two keywords to support modularization, import, and export, which are keywords rather than functions for js and work on their AST rather than their runtime. (Conditional import is therefore not supported)
let flag = 1 if(flag == 1){ import {value,say_sm} from './module/lib04.js' } //Interpretation-time errors occur because if conditions need to wait until execution-time to be determined, which cannot be determined when compiling to AST, and import starts generating code at compilation-time. So direct parse syntax error
Noejs support for CommonJS
//lib.js let value = 'value' function say_sm(){ console.log(value) } module.exports.value = value module.exports.say_sm = say_sm
//bob.js const lib = require('./lib.js') console.log(lib.value) lib.say_sm()
This is the modular support (non-language level support) in nodejs, where each js file is a module, and in nodejs, there is a global object module, which is an instance of the Module class, which has a property, exports, and is also an object. Default initialization is {} (an object without attributes) when the module instance is created (in order to "thoroughly" support the commonjs specification, there is also an attribute export in the module instance, which is directly assigned to module.exports, that is, export = module.exports)
The function require returns an object directly, not a new object, but a lib. Properties (objects) exports in object module in JS module

So node support for commonjs is essentially about object sharing.
When a js file is loaded, node instantiates a module object and creates an exports object
let module = new Module() module.exports = {}
This module. The exports object is located at an address in heap memory X.
When other modules reference lib. When JS (require), return address_directly X address value (object)

Other JS modules require the same lib. When js, the essence is to share modules. Exports object, so any module's modifications to the exports object will be reflected in other JS files
//bob.js const lib = require('./lib.js') lib.value = 'bob' //In other JS files require('./lib.js'), the value of value is also modified to bob
There is no problem with module support in ES6. The mechanism is not through shared objects, but through Binding Env Block mechanism during AST.

Above is the import and export in the basic Js