Node.js API实例讲解——node.js模块机制
node.js模块机制
模块化的作用是可以让代码更易于管理。下面开发2个模块,然后用主程序加载这2个模块。
main.js
// math.js // 加法 exports.add = function(a,b){ return a+b; } // 减法 exports.cut = function(a,b){ return a-b; }
math2.js
module.exports = { // 除法 division:function(a,b){ return a/b; }, // 乘法 multipli:function(a,b){ return a*b; } }
main.js
// 加载math模块 var math = require("./math"); // 加载math2模块 var math2 = require("./math2"); console.log(math.add(6,3)); // 9 console.log(math.cut(6,3)); // 3 console.log(math2.division(6,3)); // 2 console.log(math2.multipli(6,3)); // 18
main.js是主程序,通过require加载模块,exports 和 module.exports 是模块的出口,exports 是 module.exports 的辅助写法,module.exports = xxx 这种写法是合法的,而exports = xxx这种写法是错误的,exports.xxx = xxx这种写法才是合法的。
如果定义的模块中同时使用 moudle.exports 和 exports ,那么会忽略exports的定义,看下面的代码。
修改后的math2.js
// 修改后的math2.js exports.division = function(a,b){ return "-----"; } module.exports = { // 除法 division:function(a,b){ return a/b; }, // 乘法 multipli:function(a,b){ return a*b; } } exports.division = function(a,b){ return "-----"; }
主程序 main.js
//主程序 main.js // 加载math模块 var math = require("./math"); // 加载math2模块 var math2 = require("./math2"); console.log(math.add(6,3)); console.log(math.cut(6,3)); console.log(math2.division(6,3)); // 2 console.log(math2.multipli(6,3));
运行后会发现,exports.division在遇到module.exports时会无效。
知道如何定义模块后,回过头来看看模块的分类,模块分为核心模块,文件模块。
核心模块
核心模块就是核心库,例如http模块,当通过require("http")模块时,即使自己定义了http模块,但系统还是会返回核心模块。
文件模块
除了核心模块,都是文件模块,也就是自己定义的模块文件。
文件模块的位置
加载文件模块可以采用绝对路径,相对路径和node_modules目录下。
相对路径和绝对路径这里就不解释了,node_modules目录下的意思是require会先查找当前目录下是否有 node_moudules目录,如果有会先在这个目录查找模块,如果没有再向上级目录找是否有node_moudles目录一直到根目录,如果都没有会抛出异常。如果把模块放在node_moudles目录下,那么采用require("modulename")写法和加载核心目录的写法一致,这个要区别于相对目录的require("./modulename")写法。
文件模块的扩展名
require("./test.js") 如果写了完整的文件名会准确加载这个文件,如果没有写入扩展名require("./test"),那么会尝试加载 test.js 然后是test.json。 系统会把test.js解析为一个js文件,而会把test.json解析为一个json文件。
package.json 定义包
在main.js启动文件的当前目录下,创建一个mymodule的文件夹。该目录下创建一个package.json,内容如下:
{ "name":"math", "main":"./math.js" }
然后在package.json统计目录下顶一个math.js文件。
exports.add = function(a,b){ return a+b; } exports.cut = function(a,b){ return a-b; }
然后main.js主文件加载mymoudle模块。
var math = require("./mymodule");
如果在mymodule目录下找不到package,会尝试找mymodule/index.js文件加载。
god模块加载就讲这么多,多练习掌握模块加载的规律就熟了。下一节探讨一下module的属性和方法。
module的属性与方法
module.exports
上一节已有详细介绍,但要注意一点,module.exports 必须要立即执行,否则模块不会被加载,看下面代码:
setTimeout(function() { module.exports = { a: "hello" }; }, 0);
以上模块不会被加载。
module.require(id)
require是module.require的简写方式。
module.id
模块文件的完整路径,main.js如果是主启动文件,那么它自身调用 console.log(module.id) ,只会打印出 "." 。
module.filename
这个和module.id功能一样,即使是main.js调用console.log(module.filename)也会打印出完整的文件路径。
module.loaded
判断模块是否被加载完成,true/false。
module.parent
得到父模块。
module.children
得到子模块。