这里主要对上个章节提到的模块引用的的深入了解介绍--commonJS
当我们编写.js文件时,我们可以
var a = ‘global’;//声明一个全局变量
在浏览器中,大量使用全局变量不好。
例如在 one.js中使用全局变量a,之后two.js中也使用了全局变量a,
由于执行的先后顺序,two.js中声明的a会重新赋值,从而改变one.js中的运行逻辑,
导致冲突。
也就是javascript语言本身并没有一种模块机制来保证不同模块可以使用相同的变量名。
如何解决这个问题?
JavaScript作为函数式编程,是支持闭包的,如果将一段js代码片段用函数包装起来,那么这个代码片段中之前的“全局变量”==>“局部变量”
var a = 'hello';
var b = 'world'
console.log(a + ' ' + b)
//以上代码片段可包装为如下方式
(function(){
var a = 'hello';
var b = 'world'
console.log(a + ' ' + b)
})()
//这样一来,原来的全局变量,现在变成了匿名函数的内部的局部变量,
//如果node.js 加载其他模块,这些模块中定义的变量将互不干扰。
闭包:能够 读取 其他函数内部变量 的函数;也可以理解为定义在函数内部的函数,
本质上闭包作为一个桥梁,连接了函数的内 与 外。
所以node利用该特性,轻易实现了模块的隔离。
模块的输出如何实现?
module.exports原理
// 准备module对象:
var module = {
id: 'hello',
exports: {}
};
var load = function (module) {
// 读取的hello.js代码:
function greet(name) {
console.log('Hello, ' + name + '!');
}
module.exports = greet;
// hello.js代码结束
return module.exports;
};
var exported = load(module);
// 保存module:
save(module, exported);
可见,变量module是Node在加载js文件前准备的一个变量,并将其传入加载函数,我们在hello.js中可以直接使用变量module原因就在于它实际上是函数的一个参数:
module.exports = greet;
通过把参数module传递给load()函数,hello.js就顺利地把一个变量传递给了Node执行环境,Node会把module变量保存到某个地方。
由于Node保存了所有导入的module,当我们用require()获取module时,Node找到对应的module,把这个module的exports变量返回,这样,另一个模块就顺利拿到了模块的输出:
var greet = require('./hello');
module.exports vs exports对比
默认情况下,Node准备的exports变量和module.exports变量实际上是同一个变量,并且初始化为空对象{};
如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;
如果要输出一个函数或数组,必须直接对module.exports对象赋值。
所以直接对module.exports赋值,可以应对任何情况
module.exports = {
foo: function () {
return 'foo';
}
};
//或者
module.exports = function () {
return 'foo';
};
网友评论