stephen's blog

[object Object] object(s)
 

Module.exports vs Exports in Node.js

前言

最近在折腾node.js的时候,经常会看到类似exports.xxx = yyy以及module.exports = yyy这样的代码,可实际上如果通过require()函数来引用模块就会有报错的情况,所以到底是什么原因造成的呢?这两者又有什么区别?
关于两者的区别,了解了下面几点就会非常的清楚:

比如以下代码计算圆的面积:

使用exports

1
2
3
4
5
6
7
8
// circle.js
exports.area = function(r){
return r*r*3
} ;
//app.js
var circle = require('./circle')
console.log(circle.area(2))
//输出 '12'

使用module.exports

1
2
3
4
5
6
7
8
// area.js
module.exports = function(r){
return r*r*3
};
//app.js
var area = require('./area')
console.log(area(2))
//输出 '12'

两者输出是一样的,因为exports是module.exports的一个引用,所以两者指向的内存地址是一样的,可是如果你这样写:

1
2
3
4
5
6
7
8
// area.js
exports = function(r){
return r*r*3
};
//app.js
var area = require('./area')
console.log(area(2))
//输出 'TypeError: object is not a function'

我们可以看到是报错的,原因在于,之前说过require()返回的只是module.exports,而exports是module.exports的一个引用,上面代码给exports重新赋值,使其指向了新的内存地址,此时exports和module.exports毫无关系,也就是说此时module.exports的值为默认值{},所以导出的是一个空对象。

也就是说,module.exports才是关键,而exports只是起辅助的作用,最终导出来的是module.exports上挂载的对象,当module.exports没有任何值时,exports挂载的属性会赋值给module.exports, 当module.exports具有挂载的对象时,exports上的所有值会被忽略,比如以下代码只输出了module.exports所挂载的属性:

1
2
3
4
5
6
7
8
//rock.js
module.exports.name = 'Stephen'
exports.name = 'Mike'
//app.js
var rock = require('./rock.js')
rock.name
//输出
'Stephen'

总结一下:

参考:

exports 和 module.exports 的区别
node-js-exports-vs-module-exports
module-exports-and-exports-in-node-js