node环境使用CommonJS规范的模块加载机制

CommonJS规范的模块加载机制与ES6的有所不同,ES6属于静态加载,直到加载模块的脚本运行才会运行要加载的模块。而CommonJS的模块是动态加载,要加载的模块先运行,然后输出一个exports对象给加载模块的脚本,exports对象的属性值已经被求值。加载模块的脚本会声明一个对象来将exports对象(浅)拷贝过来。
看如下的两份不同的代码:

module_a.js
var count = 3;
var increase = funcition () {
	count ++;
}
exports.count = count;
expors.increase = increase;

module_b.js
var mod = require('module_a.js');
console.log(mod.count); // 3
mod.increase(); // 这将改变module_a.js的count值;
console.log(mode.count); // 3

module_a.js的exports对象在加载后已经成了

exports = {
	count: 3,
	increase: increase // 这里是increase函数的引用
}

而mod从exports对象浅拷贝而来,调用increase()相当于调用module_a.js的increase函数,对mod对象并无变化;

module_a.js
var count = [1, 2, 3];
var increase = funcition () {
	count[2] = 0;
}
exports.count = count;
expors.increase = increase;

module_b.js
var mod = require('module_a.js');
console.log(mod.count); // [1, 2, 3]
mod.increase(); // 这将改变module_a.js的count值,同时因为mod.count也引用了module_a.js的count值,会改变mod.count的值;
console.log(mode.count); // [1, 2, 0]

当count值为引用类型时,传递给mod.count的是引用类型值,当module_a.js的count值变化时,mod.count自然也会发生变化。

因此,在加载模块时,要注意模块exports对象的属性值是否是引用类型。如果是引用类型值,更改模块内部变量时,会导致加载模块的脚本的属性值也跟着一起改变。
导入模块时,模块运行一遍输出闭包exports,因此各个文件对于模块的更改都是在自己的作用域范围内,不会互相影响。

你可能感兴趣的:(node.js)