译自http://www.hacksparrow.com/node-js-exports-vs-module-exports.html
Nodejs中的exports和module.exports有什么区别?
你肯定对nodejs中的exports
概念有所了解,如下在nodejs的模块中创建函数(假设有个rock.js
的文件)
exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
在其他文件中这样引入并使用:
var rocker = require('./rocker.js');
rocker.name(); // 'My name is Lemmy Kilmister'
module.exports究竟是什么?甚至它是否合法呢?
令人大开眼界的是module.exports才是真实引用,exports不过是其一个辅助。
模块真正返回的是module.exports
的引用给调用者,而非exports。
exports所做的是收集属性并绑定到module.exports
。前提是module.exports
对象上未有绑定。
如果module.exports
已有绑定,exports的收集则被忽略。
添加如下代码到rock.js
:
module.exports = 'ROCK IT!';
exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
引用时:
var rocker = require('./rocker.js');
rocker.name(); // TypeError: Object ROCK IT! has no method 'name'
rocker模块忽略exports.name并返回一个字符串‘ROCK IT’,你或许发现模块并不一定非得返回一个实例化的模块,
可以是任意的javascript数据类型。你的模块返回是任意设置给module.exports
的值。
如果没有设置module.exports
,则使用exports给module.exports
绑定属性、方法。
下面的例子,模块是一个类:
module.exports = function(name, age) {
this.name = name;
this.age = age;
this.about = function() {
console.log(this.name +' is '+ this.age +' years old');
};
};
这样去使用:
var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old
你的模块还可以是一个数组:
module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];
使用:
var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); //Rockin in heaven: Ronnie James Dio
如果你想你的模块是特定类型,你可以使用module.exports。如果你想你的模块是个实例化的对象,可以使用exports。
给moduels.exports添加属性和exports上添加属性类似,如下:
module.exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
同理:
exports.name = function() {
console.log('My name is Lemmy Kilmister');
};
但是两者不是一个东东。如前面所说,module.exports是最后的引用而exports只是其一个辅助。
只要你没有给module.exports作赋值操作。在require操作的引用模块里,module.exports和exports都可以获取到。
模块如下:
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
引用:
var rocker = require('./rocker.js');
console.log('%s is %s', rocker.name, rocker.age); // Lemmy Kilmister is 68
如果你复写了module.exports对象,那么上面的require就不能“如愿”获取。
module.exports = 'LOL';
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
或者
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
module.exports = 'WTF';
上面的例子可以看出,module.exports重新赋值的操作所在位置的不同不影响结果。
即:打印rocker.age 和 rocker.name 的值都会是 undefined。
注意: 虽然module.exports.age 和 exports.name 都会被导出,但是不建议用这种方式。
我的建议是优先使用** exports.* **。