CommonJS规范规定,每个模块内部,module
变量代表当前模块。这个变量是一个对象,它的exports
属性(即module.exports
)是对外的接口。加载某个模块,其实是加载该模块的module.exports
属性。
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
上面代码通过module.exports
输出变量x
和函数addX
。
require
方法用于加载模块。
var example = require('./example.js'); console.log(example.x); // 5
console.log(example.addX(1)); // 6
Node内部提供一个Module
构建函数。所有模块都是Module
的实例。
function Module(id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
// ...
module.exports
属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports
变量。
为了方便,Node为每个模块提供一个exports变量,指向module.exports。这等同在每个模块头部,有一行这样的命令。
var exports = module.exports;
造成的结果是,在对外输出模块接口时,可以向exports对象添加方法。
exports.area = function (r) {
return Math.PI * r * r;
}; exports.circumference = function (r) {
return 2 * Math.PI * r;
};
注意,不能直接将exports变量指向一个值,因为这样等于切断了exports
与module.exports
的联系。
exports = function(x) {console.log(x)};
上面这样的写法是无效的,因为exports
不再指向module.exports
了。
下面的写法也是无效的。
exports.hello = function() {
return 'hello';
}; module.exports = 'Hello world';
上面代码中,hello
函数是无法对外输出的,因为module.exports
被重新赋值了。
这意味着,如果一个模块的对外接口,就是一个单一的值,不能使用exports
输出,只能使用module.exports
输出。
module.exports = function (x){ console.log(x);};
如果你觉得,exports
与module.exports
之间的区别很难分清,一个简单的处理方法,就是放弃使用exports
,只使用module.exports
。
---------------------------------------------------------------------------------------------------------------------
require命令
Node使用CommonJS模块规范,内置的require
命令用于加载模块文件。
require
命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。
如果模块输出的是一个函数,那就不能定义在exports对象上面,而要定义在module.exports
变量上面。
require
命令用于加载文件,后缀名默认为.js
。
var foo = require('foo');
// 等同于
var foo = require('foo.js');