ES6: Module loading, compared with CommonJS

ES6: Module loading

Differences between ES6 modules and CommonJS modules

  • The output of CommonJS is a copy value of a value, and the output of the ES6 module is a reference to a value. That is to say, changing the value output by the CommonJS module will not affect the value of the module itself, while ES6 will affect the same The value of a module reference.
  • CommonJS is loaded at runtime, and ES6 is the output interface at compile time.

The import command loads the CommonJS module

  • In the Node environment, use the import command to load the CommonJS module, and Node will automatically use the module.exports property as the default output of the module, which is equivalent to export default.

    // a.js
    module.exports = {
          
          
        foo : "hello"
    }
    
    // 等同于
    module export {
          
          
    	foo : "hello"
    }
    
    // 引入
    import baz from './a';
    import {
          
          default as baz} from './a';
    // baz === { foo : "hello"};
    
  
- 如果采用整体输入的方法,default将会取代module.exports作为输入的接口

  ```js
  import * as baz from './a';
  // baz === {
  //	  get default(){
  //        return module.exports;
  //    },
  //    get foo(){
  //        return {this.default.foo}.bind(baz);
  //    }
  //}
  • In the above example, this.default replaces module.exports, and it is not difficult to see that the import syntax will add the default attribute to baz.

require command to load ES6 module

  • When using require to load an ES6 module, all output interfaces of the ES6 module will become attributes of the input object

    // a.js
    let foo = {
          
          
        bar : "hello"
    }
    export default foo;
    
    
    // b.js
    const amodule = require('./a.js');
    // amodule.default === {bar : "hello"}
    

Cyclic loading

  • The so-called cyclic loading means that two modules refer to each other, causing the program to execute recursively, and the two modules deal with this in different ways.

Cyclic loading of CommonJS

  • CommonJS module loading principle: no matter how many times a cjs module is loaded, it will only run once when it is loaded for the first time, and all subsequent loading will be the result of the first return, unless the cache is manually cleared;

    // a.js
    export.done = false;
    let b = require('./b');
    console.log('在a.js中,b.done = %j',b.done);
    export done = true;
    console.log('在a.js中,b.done = %j',b.done);
    console.log('a.js执行完毕');
    
    // b.js
    export.done = false;
    let a = require('./a');
    console.log('在b.js中,a.done = %j',a.done);
    export done = true;
    console.log('在b.js中,a.done = %j',a.done);
    console.log('b.js执行完毕')
  • In the above code, b.js will be executed when a.js is executed to the second line, and a.js will be executed when b.js is executed in the second line, and the system will automatically go to a.js to find the corresponding export Value, but a.js has not been executed yet, therefore, only values ​​that have been executed can be extracted from the exports value.

    // main.js
    var a = require('./a');
    var b = require('./b');
    console.log('在main.js中,a.done = %j,b.done = %j',a.done,b.done);
    
    // 输出
    在b.js中,a.done = false;
    b.js执行完毕;
    在a.js中,b.done = true;
    a.js执行完毕;
    在main.js中,a.done = true,b.done = true;
    
  • The above code proves that the execution of the main file to the second line will not re-execute b.js, but directly return its final value.

Cyclic loading of ES6 modules

  • Since ES6 modules are dynamically referenced, variables will not be cached, but point to the referenced object.

    // a.js
    import {
          
          bar} from "./b.js";
    console.log("a.js");
    console.log(bar);
    export let foo = 'foo';
    
    // b.js
    import {
          
          foo} from "./a.js";
    console.log("b.js");
    console.log(foo);
    export let bar = "bar";
    
    
    // 执行a.js
    b.js
    undefined
    a.js
    bar
    
  • The above code, a.js is executed, the first line of code references b.js, so b.js is run, and the first line of b.js is to introduce a.js, because a.js is already running, it will not be loaded again Once, undefined is output, and then executed normally.

Comparison of the two modes

// a.js
import {
    
    bar} from "./b.js"
export function foo(){
    
    
    console.log('foo');
    bar();
    console.log('执行完毕');
}
foo();

// b.js
import {
    
    foo} from "./a.js"
export function bar(){
    
    
    console.log('bar');
    if(Math.random() > 0.5){
    
    
        foo();
    }
}
  • The above piece of code cannot be executed under the CommonJS standard. a loads b, and then b loads a. At this time, the execution of a has not ended, so the output result will be null, that is null, the value of foo for b , so it cannot be executed, and an error will be reported;
  • Under the ES6 standard, because import creates a reference to an object, when a is loaded, the first line of code creates a barreference to b.js, and when it runs to the fourth line of code, it will jump to b.js Execute bar(); then execute the console of the next line of code.

Guess you like

Origin blog.csdn.net/yivisir/article/details/109372174