今天的内容涉及到Node的原理、运行机制和CommonJS的内容。会有点枯燥和困难。建议像我一样做一些笔记。在开发大型应用程序时,我们经常会用到全局变量,例如:vars="Hello"。但是,当我们的应用程序越来越大时,我们可能会不小心重复使用几个相同的变量或函数名,这会给我们的应用程序带来麻烦。为了解决这个困难,提出了模块的概念。模块是一种代码组织形式,就是将实现不同功能的JS代码分别编写,将同名的函数或变量存放在不同的模块中,这样可以避免同名函数或变量之间的冲突。同时,模块也可以提高代码的可维护性。因为你只需要关心编写当前模块,而不必担心污染或影响其他模块,而且模块之间是相互隔离的。在上一节的例子中,我们写了一段hello.js的代码。在这里,我们修改一下:'usestrict';vars="Hello";functiongreet(name){console.log(s+","+name+"!");}module.exports=greet;在这里,我们使用module.exports来导出一个变量。这个变量是这个模块和外界之间的一个出口。这个变量可以是一个函数,一个对象,一个数组。既然有输出,就必然有接口。让我们创建另一个main.js:'usestrict';//引入hello模块:varheat=require('./hello');vars='Michael';heat(s);//你好,迈克尔!在这里,我们导入带有require函数的hello模块。在main.js中,变量heat就是hello.js中暴露的greet函数。接下来的热量`是直接使用它。Commonjs规范和Node内部运行的这种模块加载方式称为Commonjs规范。除了这个规范,还有ES6、AMD、CMD。这里就不细说了,我也没有学过。我只是在这里说一下。Commonjs和之前学过的闭包知识。上面,我们提到了与全局变量的冲突。如我们上面的例子,两个js文件都声明了变量s,但是没有冲突,依然按照我们的意愿执行。这就是Node对模块隔离的实现。隔离原理Node因为闭包可以实现模块和变量的隔离。JS是一种支持闭包的函数式编程语言。如果我们用一个函数包装一个变量,这个变量就变成了函数内部的一个局部变量。而我们知道,只要这个函数在闭包中的生命周期没有结束,这个变量就可以一直存在,不受其他函数之外的其他变量的影响。我们用上面的例子来说明,在hello模块中,保存了s="hello",只开了一个开口:module.exports=greet,在函数greet中,包含了变量s,所以"s=hello"可以保存,直到greet在主模块中被引用。这里有一个问题。我们说我们需要一个函数来形成一个闭包,但是我们的代码没有这个函数?这就是Node所做的。Node帮我们把hello模块包装在里面:(function(){vars="Hello";functiongreet(name){console.log(s+","+name+"!");}})()因此,s成为匿名函数的内部局部变量,即使后面加载的其他模块中有s变量,这个s变量也不会受到影响。模块的输出在Node中有一个模块对象,我们看一下模块的输出过程:varmodule={id:'hello',exports:{}};varload=function(module){//读取hello.js代码functiongreet(name){console.log("Hello,"+name+"!");}module.exports=问候;//hello.js代码结束returnmodule.exports;};varexported=load(module);//保存模块save(module,exported);在我们的hello模块中,我们通过module.exports=greet传递了一个变量给Node,而module其实是Node准备阶段的一个变量,同时也是作为load函数的参数保存的。每当我们使用module.exports时,Node都会按模块分类保存一个模块,这些模块都保存在一起。当我们要在主模块中使用hello模块时,我们使用require()让Node帮我们找到id为hello的模块并传递给我们。这样我们就得到了hello的模块输出。Node的操作参考模块——廖雪峰官网。看完后有点懵。不过我们暂时可以先看看Node处理模块的工作原理,等了解了主要内容之后再详细分析。两种输出方式我们可以通过两种方式导出模块:方式一:module.exports={hello:hello,greet:greet}方式二:exports.hello=hello;exports.greet=打招呼;但是不能直接export赋值:exports={hello:hello,greet:greet}实践证明还是用module.exports=xxx赋值比较好。具体原因还涉及到Node内部的处理。有兴趣的同学可以参考上面的文章。
