CommonJS和ES6module的异同

开头总结

1 相同点
都是前端模块化的一种
2 不同点

  • 前者利用exports和module.exports导出数据,用require导入;后者利用export和export default导出,利用import导入
  • 前者是动态化加载,可以放在块级作用域中使用;后者是静态加载,在编译的时候就处理了。
  • 前者导出的数据如果是基本数据类型,导出的是拷贝,引用数据类型的话则是引用。后者导出的都是原数据的引用。
  • 前者可以解决循环引用的问题,后者不能解决

    不同点分析

    第一点

    // c.js
    exports.name = "mike";
    module.exports = {
      name: "mike"
    }
    // d.js
    let c = require('./c');
    console.log(c); // { name: 'mike' }

    对于ES6module要在package.json中增加"type": "module"或者采用.mjs扩展名,下面演示代码采用后者

    // b.mjs
    export let a = "hello world";
    const b = "这是b"
    export default b;
    // a.mjs
    import b, {a} from './b.mjs'
    console.log(a); // hello world
    console.log(b); // 这是b
    // 对于export default的变量,引入的时候不需要加{},export的变量需要加{}

    第二点

    CommonJS如下
    只改变d的内容

    // d.js
    function say() {
      let c = require('./c');
      console.log(c);
    }
    say(); // { name: 'mike' }

    ES6module如下
    只改变a.mjs

    function say() {
      import b, {a} from './b.mjs'
      console.log(a);
      console.log(b);
    }
    say(); // 报错

    第三点

    对于CommonJS

    // c.js
    module.exports = "hello world"
    // d.js
    let a = require('./c')
    a = "hi, world"
    console.log(a);
    let b = require('./c')
    console.log(b);
    //hi, world
    // hello world
    
    // 引用数据类型的情况
    // c.js
    exports.name = "hello, world"
    // d.js
    let a = require('./c')
    a.name = "hi, world"
    console.log(a);
    let b = require('./c')
    console.log(b);
    // 
    { name: 'hi, world' }
    { name: 'hi, world' }

    对于ES6module

    // a.mjs
    let a = "hello, world";
    export {a}
    
    // b.mjs
    import {a} from './a.mjs'
    a = "hi, world"
    console.log(a);
    // 报错,Assignment to constant variable.

    因为ES6module导出的是引用,默认导出的是const变量,所以禁止更改其值,修改了则报错.

解决循环引用

1 CommonJS中采用了缓存,对于已经一个模块,require()函数先去缓存中寻找是否已经加载,如果加载了直接从缓存中取;否则先缓存该模块,再去执行,(注意顺序) 有了缓存很好的解决了循环引用的问题。
如下例子存在main.js c.js d.js三个文件, c和d互相引用,main引用c和d

// c.js
let d = require('./d');
console.log("这是c");

// d.js
let c = require('./c')
console.log("这是d");

// main.js
let c = require('./c')
let d = require('./d')
console.log("这是main");
// 结果 
// 这是d
// 这是c
// 这是main
// 而且发现d仅执行了一次,验证了缓存的说法, 当执行到c的第一行的时候,c已经被缓存了,进入d执行第一行的时候,是从缓存中取的c,此时c只是被缓存了还未被执行。

2 ES6module对于循环引用会报错。

你可能感兴趣的:(CommonJS和ES6module的异同)