JSmodular

1. Modular development history

  • IIFESelf-executing function
  • AMDuserequireJSTo write modularity (dependencies must be declared in advance.)
  • CMDuseseaJSTo write modularity (support dynamic introduction of dependent files.)
  • CommonJS nodeJsBuilt-in modularity in
  • UMDCompatible withAMD,CommonJSgrammar
  • webpack(require.ensure):webpack 2.xCode splitting in version
  • ES Modules:ES6Introduction of modularity supportimportLet’s introduce another onejs
  • scriptThe labeltype="module"

2,AMDCMDThe 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

  • AMDDependency preloading is preferred. When defining a module, you should declare the module that it depends on
  • CMDUse proximity only when you need a modulerequire

3,CommonJSSpecification characteristics

  1. So the code runs in the module scope and does not pollute the global scope
  2. Modules are loaded synchronously, and subsequent operations will not be performed until the imported modules are loaded
  3. Modules are cached after the first execution, and reloading only returns cached results
  4. CommonJSThe 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 modulesWhat are the characteristics of the specification

  1. The output usingexport
  2. Introduction to useimport
  3. You can useexport ... from ...To achieve a transit effect
  4. Input module variables are not reassigned. It’s just a readable reference, but you can overwrite properties
  5. exportimportCommands are at the top of the module, can’t be scoped, in a code block, can’t do static optimization, brokenES6The design intention of the module
  6. importThere is a promotion effect, will be promoted to the head of the entire module, execute first
  7. Babeltheexport/importintoexports/requireForm, so can be usedexportsimport

5,CommonJSES6 ModulesSpecification distinction

  1. CommonJSModules are loaded at runtime,ES6ModulesIt is loaded at compile time
  2. CommonJSA copy of the output value,ES6ModulesReferences to output values (changes within the module affect references)
  3. CommonJSAn import module can be an expression (which is usedrequire()The introduction of),ES6ModulesImports can only be strings
  4. CommonJSWhere this refers to the current module,ES6ModulesthisPoint to theundefined
  5. ES6ModulesThere is noarguments,require,module,exports,__filename,__dirnameThese 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?

  1. security
  2. closed
  3. Avoiding variable conflicts
  4. Isolation scope
  5. The pull-out of common code

Eight,node require(X)What is the processing order introduced?

  1. ifXIs a built-in module, returns the module, and does not continue execution;
  2. ifX'./', '/', '.. / 'The beginning will be based onXParent module, okXThe absolute path to: aXAs a file, search in sequence, exist, return the file, do not continue to execute; B. willXIf the file exists, the system returns the file and does not continue the execution.
  3. ifXWithout a path: a. According toXParent module, okXPossible installation directories b. In each directory in turn, willXLoad as filename or directory name
  4. thrownot founderror

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
  1. a.jsThe script starts by printing onedoneVariable, and then load another script fileb.js. Notice that at this pointa.jsThe code just sits there and waitsb.jsAfter the command is executed, proceed to the next step.
  2. b.jsThe second line is loadeda.jsAt this point, “cyclic loading” occurs. The system will go toa.jsOf the module corresponding to the objectexportsProperty value, but becausea.jsIt’s not done yet, fromexportsProperty can only fetch what has already been executed, not the last value.
  3. a.jsThe part that has been executed is only one line.
exports.done = false;
Copy the code
  1. Therefore, forb.jsIn terms of it froma.jsEnter only one variabledoneAnd has a value offalse.
  2. b.jsAnd then it goes down, and when it’s all done, it gives it backa.js. As a result,a.jsThen proceed until the execution is complete. Let’s write a scriptmain.jsAnd 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
  1. The code above proves two things. One is inb.js,a.jsOnly the first line is executed. The second is,main.jsThe second line is not executed againb.jsIt is output cachedb.jsThe 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