JS
modular
1. Modular development history
IIFE
Self-executing functionAMD
userequireJS
To write modularity (dependencies must be declared in advance.)CMD
useseaJS
To write modularity (support dynamic introduction of dependent files.)CommonJS
nodeJs
Built-in modularity inUMD
Compatible withAMD
,CommonJS
grammarwebpack(require.ensure)
:webpack 2.x
Code splitting in versionES Modules
:ES6
Introduction of modularity supportimport
Let’s introduce another onejs
script
The labeltype="module"
2,AMD
和 CMD
The difference between
The biggest difference between AMD and CMD is that the execution time of the dependent module is different. Note that it is not the loading time or the way is different. Both are asynchronous loading modules
AMD
Dependency preloading is preferred. When defining a module, you should declare the module that it depends onCMD
Use proximity only when you need a modulerequire
3,CommonJS
Specification characteristics
- So the code runs in the module scope and does not pollute the global scope
- Modules are loaded synchronously, and subsequent operations will not be performed until the imported modules are loaded
- Modules are cached after the first execution, and reloading only returns cached results
CommonJS
The output is a copy of the value, and changes within the module do not affect the value (reference type and base type are different).
4,ES6 modules
What are the characteristics of the specification
- The output using
export
- Introduction to use
import
- You can use
export ... from ...
To achieve a transit effect - Input module variables are not reassigned. It’s just a readable reference, but you can overwrite properties
export
和import
Commands are at the top of the module, can’t be scoped, in a code block, can’t do static optimization, brokenES6
The design intention of the moduleimport
There is a promotion effect, will be promoted to the head of the entire module, execute firstBabel
theexport/import
intoexports/require
Form, so can be usedexports
和import
5,CommonJS
和 ES6 Modules
Specification distinction
CommonJS
Modules are loaded at runtime,ES6Modules
It is loaded at compile timeCommonJS
A copy of the output value,ES6Modules
References to output values (changes within the module affect references)CommonJS
An import module can be an expression (which is usedrequire()
The introduction of),ES6Modules
Imports can only be stringsCommonJS
Where this refers to the current module,ES6Modules
中this
Point to theundefined
ES6Modules
There is noarguments
,require
,module
,exports
,__filename
,__dirname
These top variables
6. How to load modules asynchronously
AMD and CMD support asynchronous loading of modules
7. What issues should be considered when developing a module?
- security
- closed
- Avoiding variable conflicts
- Isolation scope
- The pull-out of common code
Eight,node require(X)
What is the processing order introduced?
- if
X
Is a built-in module, returns the module, and does not continue execution; - if
X
以'./', '/', '.. / '
The beginning will be based onX
Parent module, okX
The absolute path to: aX
As a file, search in sequence, exist, return the file, do not continue to execute; B. willX
If the file exists, the system returns the file and does not continue the execution. - if
X
Without a path: a. According toX
Parent module, okX
Possible installation directories b. In each directory in turn, willX
Load as filename or directory name - throw
not found
error
9. Node references each other
There are two files a.js and B.js, which refer to each other
1. CommonJS
{
id: '... '.exports: {... },loaded: true.parent: null.filename: ' '.children: [].paths: []}Copy the code
CommonJS module is a script file. The first time the script is loaded, the require command executes the entire script and then generates an object in memory. The module will be exported to the exports property when needed. Even if the require command is executed again, the module is not executed again, but is evaluated in the cache.
An important feature of CommonJS is that it is executed at load time, and all script code is executed at require.
The CommonJS approach is that once a module is “loop-loaded”, only the parts that have been executed are printed, and the parts that have not been executed are not.
// a.js
exports.done = false;
var b = require('./b.js');
console.log('in a.js, b.tone = %j', b.done);
exports.done = true;
console.log('A.js completed');
//b.js
exports.done = false;
var a = require('./a.js');
console.log('在 b.js 之中,a.done = %j', a.done);
exports.done = true;
console.log('B.js completed');
Copy the code
a.js
The script starts by printing onedone
Variable, and then load another script fileb.js
. Notice that at this pointa.js
The code just sits there and waitsb.js
After the command is executed, proceed to the next step.b.js
The second line is loadeda.js
At this point, “cyclic loading” occurs. The system will go toa.js
Of the module corresponding to the objectexports
Property value, but becausea.js
It’s not done yet, fromexports
Property can only fetch what has already been executed, not the last value.a.js
The part that has been executed is only one line.
exports.done = false;
Copy the code
- Therefore, for
b.js
In terms of it froma.js
Enter only one variabledone
And has a value offalse
. b.js
And then it goes down, and when it’s all done, it gives it backa.js
. As a result,a.js
Then proceed until the execution is complete. Let’s write a scriptmain.js
And run to verify the process.
// main.js
var a = require('./a.js');
var b = require('./b.js');
console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);
/ / run
// in b.js, a.tone = false
// b.js The execution is complete
// in a.js, b.tone = true
// a.js The execution is complete
// 在 main.js 之中, a.done=true, b.done=true
Copy the code
- The code above proves two things. One is in
b.js
,a.js
Only the first line is executed. The second is,main.js
The second line is not executed againb.js
It is output cachedb.js
The execution result of, its fourth line.
2. ES6
The ES6 module operates differently from CommonJS in that when it encounters the module load command import, it does not execute the module, but only generates a reference. Wait until you really need to use it, and then go to the module to value.
ES6 module is dynamic reference, there is no cache value problem, and the variables in the module, bound to its module. ES6 modules do not cache run results, but dynamically remove loaded module values, and variables are always bound to the module in which they reside.
ES6 doesn’t care if “loop-loading” occurs or not, it just generates a reference to the loaded module, requiring the developer to ensure that the value is retrieved when it is actually evaluated.
// even.js
import { odd } from './odd'
export var counter = 0;
export function even(n) {
counter++;
return n == 0 || odd(n - 1);
}
// odd.js
import { even } from './even';
export function odd(n) {
returnn ! =0 && even(n - 1);
}
Copy the code
According to the CommonJS specification, it will not load, will report an error, but ES6 can be executed. This is possible because ES6 loads variables that dynamically reference their modules. As long as the reference exists, the code executes.
$ babel-node
> import * as m from './even.js';
> m.even(10);
true
> m.counter
6
> m.even(20)
true
> m.counter
17
Copy the code
In the code above, foo() is executed six times as n goes from 10 to 0, so the variable counter is equal to 6. On the second call to even(), the argument n changes from 20 to 0, foo() is executed 11 times, plus the previous six, so the variable counter is equal to 17.
Refer to the article
Cyclic loading of JavaScript modules