本文英文链接:http://www.hacksparrow.com/node-js-exports-vs-module-exports.html
你肯定熟悉nodejs模块中的exports对象,可以在你的模块中用它创建函数(假设文件名为rocker.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的辅助工具。你的模块最终返回给调用者的是module.exports,而不是exports。当module.exports上没有值存在的情况下,exports收集属性,并把它们附加到module.exports上。如果module.exports上已经有属性了,exports将被忽略。
把下面的代码放到rocker.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对象-boolean,number,date,JSON,string,function和array等。模块无所谓是否设置module.exports。如果你没有显式地设置module.exports,那么exports的属性将会附加到module.exports上,然后返回。
在这种情形下,模块是个class:
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。
把属性附加在module.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只是辅助工具而已。话虽如此,如果你不计划改变模块对象类型从传统的模块实例至其它,exports是个推荐使用的对象。
如果,你没有对module.exports对象进行赋值,任何附加在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,代码运行会失败:
module.exports = 'LOL';
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
或
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
module.exports = 'WTF';
无所谓顺序,rocker.age和rocker.name会是为定义。
同时,只是因为module.exports.age和exports.name都被导出,这不意味这你可以结合两者一起使用。我推荐使用exports.*,同时注意module.exports.*。