1:EsModule与CommonJS的差异:

  • CommonJS模块输出的是一个值的拷贝,而EsModule模块输出的是值的引用
  • CommonJs模块是运行时加载,EsModule则是编译时执行
  • CommonJs的this是当前模块,而EsModule的this是undefined

2:CommonJs - 值的拷贝:

实质上是一个浅拷贝:

文章目录
  • 假设exports指向的对象地址值为:0x01。
  • 当使用require()加载导出的对象后,它会进行浅拷贝,然后返回浅拷贝的对象地址值,并不指向0x01。
// lib.js
var counter = 3;

// ⑤:走这里执行
function incCounter() {
  counter++;
  console.log(counter); // 4
}

// ①:假设exports对象的地址值是0x01,将其导出.
module.exports = {
  counter: counter,
  incCounter: incCounter,
};
// main.js

// ②:在使用require()时,会进行浅拷贝,假设mod为0x02.
var mod = require('./lib');

// ③:浅拷贝后,从0x01中复制了一份,基本类型再怎么修改,也不会影响到0x01,这里打印的是0x02中的counter.
console.log(mod.counter);  // 3
// ④:浅拷贝时,如果是函数,拷贝的其实是个引用,它引用的源头是在0x01里,所以去0x01里执行.
mod.incCounter(); // 4
// ⑤:再次打印mod,还是走0x02中的counter.
console.log(mod.counter); // 3

3:EsModule - 值的引用

EsModule对引入的变量是一个动态只读引用

  • 动态是指:变量在a模块发生了变化,在b模块也会发生变化,由于是一个引用,所以存在映射关系。
  • 只读是值:不能修改引入变量的值,不管是什么数据类型。
// lib.js
var counter = 3;

function incCounter() {
  counter++;
}

// 暴露对象的地址值: 0x01
export default {
  counter: counter,
  incCounter: incCounter,
};
// main.js
// 当引入后,mod变量存储的就是0x01的引用.
import mod from './lib.js';

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