1、什么是模块
开始编写Node应用之前,必须先学会Node的模块和包。模块和包是组成应用的基本单位。一个Node.js文件就是一个模块,这个文件可能是Javascript代码、JSON或者编译过的C/C++扩展。
例如:simple.js
var count=0;
exports.next=function(){return count++;}
实例:
从require('./simple')返回的这个对象正是我们在simple.js中定义的exports。每一次对s.next()调用都是对simple.js里next函数的调用,然后next函数返回自增count变量值。
Node里有三种定义模块的方式:
相对路径定义方式(以 ./或者../开头)、绝对路径定义方式(以 /开头)和顶级目录的定义方式(以模块名开头)。
2、创建模块
在Node.js中,创建一个模块非常简单,应为一个文件就是一个模块,我们要关注的问题仅仅在于如何在其他文件中获取这个创建的模块。Node.js提供了exports和require两个对象,其中exports是模块公开的接口,require用于从外部获取一个模块的接口,即所获取模块的exports对象。
创建module.js模块
var name;
exports.setName=function(thyName){name=thyName;};
exports.sayHello=function(){console.log("Hello "+name);};
创建getmodule.js调用模块module.js
var module=require('./module');
module.setName('Public');
module.sayHello();
最后运行结果是:Hello Public
module.js通过exports对象把setName和sayHello作为模块的访问接口,在getmodule.js通过require('./module')加载这个模块,然后就可以直接访问这里面的成员函数了。npm提供提供的上万个模块都是这种简单的方式搭建起来的。
3、单次加载
require不会重复加载模块,也就是说无论调用多少次require,获得的模块都是同一个。
根据getmodule.js修改为loadmodule.js
var hello1=require('./module');
hello1.setName('Tom 1');
var hello2=require('./module');
hello2.setName('Tom 2');
hello1.sayHello();
运行结果是:Hello Tom 2
从结果可知,前者被后者覆盖了,所以最终结果由后者决定。
4、覆盖exports
有时我们只是想把一个对象封装到模块中。
singleobject.js
function Hello()
{
var name='霍元甲';
this.setName=function(thyName){
name=thyName;
};
this.sayHello=function()
{
console.log('Hello '+name);
};
}
exports.Hello=Hello;
此时我们在其他文件中需要通过require('./singleobject').Hello来获取Hello对象,
var Hello=require('./singleobject').Hello;
var hello=new Hello();
hello.setName('Module');
hello.sayHello();
略显冗余,可以简化如下:
hello.js
function Hello()
{
var name='霍元甲';
this.setName=function(thyName){
name=thyName;
};
this.sayHello=function()
{
console.log('Hello '+name);
};
}
module.exports=Hello;
gethello.js
var Hello=require('./hello');
var hello=new Hello();
hello.setName('Module');
hello.sayHello();
注意,模块唯一的变化是将exports.Hello改成了module.exports,在外部引用该模块时,其接口对象就是要输出的Hello对象本身,而不是原先的exports.
事实上,exports本身仅仅是一个普通的空对象,即{},他专门用来声明接口。