Node.js中exports
和module.exports
有什么不同?
你肯定对Node.js模块中用来创建函数的exports
对象很熟悉(假设一个名为rocker.js的文件):
1 | exports.name = function() { |
然后你在另一个文件中调用:
1 | var rocker = require('./rocker.js'); |
但是module.exports
到底是个什么玩意儿? 它合法吗?
令人吃惊的是module.exports
是真实存在的东西。exports
只是module.exports
的辅助方法。你的模块最终返回module.exports
给调用者,而不是exports
。exports
所做的事情是收集属性,如果module.exports
当前没有任何属性的话,exports
会把这些属性赋予module.exports
。如果module.exports
已经存在一些属性的话,那么exports
中所用的东西都会被忽略。
把下面的内容放到rocker.js:
1 | module.exports = 'ROCK IT!'; |
然后把下面的内容放到另一个文件中,执行它:
1 | var rocker = require('./rocker.js'); |
rocker
模块完全忽略了exports.name
,然后返回了一个字符串 ‘ROCK IT!’。通过上面的例子,你可能认识到你的模块不一定非得是模块实例(module instances)。你的模块可以是任何合法的JavaScript对象 -boolean,number,date,JSON,string,function,array和其他。你的模块可以是任何你赋予module.exports的值。如果你没有明确的给module.exports设置任何值,那么exports中的属性会被赋给module.exports中,然后并返回它。
在下面的情况下,你的模块是一个类:
1 | module.exports = function(name, age) { |
然后你应该这样使用它:
1 | var Rocker = require('./rocker.js'); |
在下面的情况下,你的模块是一个数组:1
module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];
然后你应该这样使用它:
1 | var rocker = require('./rocker.js'); |
现在你应该找到要点了 - 如果你想要你的模块成为一个特别的对象类型,那么使用module.exports
;如果你希望你的模块成为一个传统的模块实例(module instance),使用exports
。
把属性赋予module.exports
的结果与把属性赋予给exports
是一样的。看下面这个例子:
1 | module.exports.name = function() { |
下面这个做的是一样的事情:
1 | exports.name = function() { |
但是请注意,它们并不是一样的东西。就像我之前说的module.exports
是真实存在的东西,exports
只是它的辅助方法。话虽如此,exports
还是推荐的对象,除非你想把你模块的对象类型从传统的模块实例(module instance)修改为其他的。
我希望这篇文章能帮助你理解exports
和module.exports
之间的不同,并且能进一步的理解模块在Node.js中是怎么工作的。