Javascript Module ES6 vs CommonJS
CommonJS 模块输出的是一个值的拷贝
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
// lib.js
var counter = 3;
function incCounter() {
counter++;
}
module.exports = {
counter: counter,
incCounter: incCounter,
};// main.js
var mod = require('./lib');
console.log(mod.counter);
mod.incCounter();
console.log(mod.counter);
lib.js 模块加载以后,它的内部变化就影响不到输出的 mod.counter 了。这是因为mod.counter是一个原始类型的值,会被缓存。
$ node main.js
3
3那麼要如何才能得到内部变动后的值?
可以写成一个函数
// lib.js
var counter = 3;
function incCounter() {
counter++;
}
module.exports = {
get counter() {
return counter
},
incCounter: incCounter,
};
上面代码中,输出的 counter 属性实际上是一个取值器函数。现在再执行 main.js,就可以正确读取内部变量 counter 的变动了。
$ node main.js
3
4ES6 模块输出的是值的引用
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的 import 有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}// main.js
import { counter, incCounter } from './lib';
console.log(counter);
incCounter();
console.log(counter);上面代码说明,ES6 模块输入的变量counter是活的,完全反应其所在模块lib.js内部的变化。
$ node main.js
3
4