es6模块和CommonJs模块的差异

437 阅读2分钟
  • commonJs模块输出的是一个值的拷贝,es6模块输出的是值的引用 commonjs模块输出的是一个值的拷贝,也就是说一旦输出,内部再变化都影响不到输出的值。请看下面的例子
main.js
  var counter = 3;
  function incCounter() {
    counter++;
  }
  module.exports = {
    counter: counter,
    incCounter: incCounter,
  };

上面代码输出counter变量和改写变量的内部方法incCounter

index.js
var mod = require('./main.js');

console.log(mod.counter);  // 3
mod.incCounter();
console.log(mod.counter); // 3

上面代码说明main.js加载以后,内部的变化时不影响外面输出的值的,内部输出的值会被缓存,下次再调用的时候走的是缓存。

// 这是commonJS源码处理缓存的方式
if(Module._cache[filename]){ // 如果存在这个值直接将exports返回即可,不会重新取值
   return Module._cache[filename].exports;
}

commonjs要想得到内部变动后的值只能写成一个函数

var counter = 3;
function incCounter() {
  counter++;
}
module.exports = {
  get counter () {
    return counter
  },
  incCounter: incCounter,
};

上面代码输出的是一个取值器,再执行index.js就可以正确读取内部变量的变动。

index.js
3
4

es6模块输出的是值的引用,JS引擎对脚本静态解析的时候遇到模块加载命令import,就会生成一个只读引用,等到脚本真正执行时,再根据这个只读引用,到被加载的模块中去取值。

test.js
var userName = '0000';
function sayHi() {
	userName = '313131'
}
export {userName, sayHi};

index.js
import {userName ,sayHi} from './test.js';
	
console.log(userName); // 3
 sayHi();
console.log(userName); // 4

上面代码中,es6模块输出的就是一个值的引用,不会缓存运行的结果,而是动态的去被加载的模块中取值

  • esModule 不能放在代码块中,只能放在顶层作用域中。
  • esModule 中的import();是异步加载,commonJS的require是同步加载。
  • commonJS模块是运行时加载,es6模块是编译时输出接口。