本日的内容触及Node的道理、运转机制和CommonJS的内容,会有点烦闷,也会有点难题,发起像我一样做一些笔记。
模块
在开辟大型运用的时刻,我们经常会用到全局变量,比方:var s="Hello"
。然则,当我们的运用越来越大时,我们可能会不小心反复用了几个雷同的变量或许函数名,这就会给我们的运用构成贫苦。为了处置惩罚这个难题,因而提出了模块的观点。模块是一种代码的组织形式,就是把完成差别功用的JS代码离开来写,把雷同名字的函数或变量存在差别的模块中,如许就可以防止雷同名的函数或变量发生争执了。
同时,模块还可以进步代码的可维护性。由于你只需体贴写好当前的模块,而没必要忧郁会污染或影响到别的模块,模块之间都是断绝的。
在上一节的例子中,我们编写了一个hello.js的代码。在这里,我们把它修正一下:
'use strict';
var s="Hello";
function greet(name){
console.log(s + "," + name + "!");
}
module.exports=greet;
这里,我们用module.exports
向外输出了一个变量。这个变量就是这个模块与外界的一个出口。这个变量可以是函数、对象、数组。
既然有输出,就要有接口。我们再建立一个main.js:
'use strict';
//引入hello模块:
var heat=require('./hello');
var s='Michael';
heat(s); //Hello,Michael!
这里,我们用require函数引入了hello模块。main.js中,变量heat就是在hello.js中暴露的greet函数。接下来heat(s)
`就是直接运用它了。
Commonjs范例和Node的内部运转
这类模块加载的体式格局被称为Commonjs范例,除了这类范例以外,另有ES6、AMD、CMD,这里不细谈,我也还没学到,这里只谈谈Commonjs和之前学的闭包学问。
在上文中,我们提到了全局变量的争执。正如我们在上面的例子中,两个js文件都声清楚明了变量s,然则并没有发生争执,仍然是根据我们的志愿来实行的,这就是Node实行了模块的断绝。
断绝的道理
Node可以完成模块和变量的断绝,是由于闭包。
JS是一种函数式编程言语,它支撑闭包,假如我们用函数把某个变量包起来,这个变量就变成了函数内部的局部变量了。而我们晓得,闭包中只需这个函数的生命周期没有完毕,这个变量也就可以一向存在,而不会遭到其他函数外的其他变量的影响。
我们以上面的例子来诠释,在hello模块中,s="hello"
被保留了起来,只对外开了一个口:module.exports=greet
,在函数greet中,包括有变量s,所以”s=hello”
能一向被保留起来,直到greet在main模块中被援用。
这里有一个题目,我们说须要一个函数才构成闭包,然则我们的代码并没有这个函数呀?这就是Node做的工作了,Node帮我们在内部包装了hello模块:
(function(){
var s="Hello";
function greet(name){
console.log(s + "," + name + "!");
}
})()
因而,s就变成了匿名函数的内部局部变量,厥后加载的其他模块中纵然也有s变量,也不会影响到这个s变量。
模块的输出
在Node中有一个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);
在我们的hello模块中,我们经由过程module.exports=greet
把一个变量传给了Node,而module实际上是Node预备阶段的一个变量,而且也是作为load函数的一个参数被保留了下来。每当我们运用module.exports
时,Node就把一条module按模块分类存了起来,这些module都被保留在了一同。
当我们在main模块中想要用到hello模块时,我们又运用require()
来让Node帮我们在找到id为hello的module通报给我们。如许,我们就拿到了hello的模块输出。
Node的运转参考了
模块—廖雪峰的官方网站,实在看的我也有点绕,不过Node处置惩罚模块的运转道理我们现在看个也许临时就够了,等学完主体内容再来细细剖析。
两种输出体式格局
我们可以经由过程两种体式格局输出模块:
要领一:
module.exports={
hello:hello,
greet:greet
}
要领二:
exports.hello=hello;
exports.greet=greet;
然则你不能直接对exports赋值:
exports={
hello:hello,
greet:greet
}
实践证明,运用
module.exports=xxx
的体式格局赋值更好。详细缘由一样触及到Node的内部处置惩罚。有兴致的同砚可以参考上面的那篇文章。