浅谈 exports 和 module.exports 的区别和使用场景
module.exports 和 exports 的作用
两者都是作为当前导出模块的挂载点
而存在, 当我们需要导出一个函数(或对象, 或直接一个变量)来供别的模块 require 引入的时候, 我们可以使用
1 | module.exports.funcName = myFunc(){} |
require()的结果是{funcName: [function]}, 可见导出的方法是作为一个属性挂载在整个大的 exports 对象上的
并且当我们为 exports.funcName 赋值的时候, exports 也会出现一个相同的 exports 的属性, 一个对象属性的改变会引起另一个对象的随之改变, 反之亦然, 二者关系见下文
我们也可以导出整个对象而不是作为导出对象的属性来导出
1 | module.exports = myFunc(){} |
不过由于 module.exports 和 exports 的相互关系, 使用这种方法进行导出的时候需要注意, 当我们这样直接为对象赋值的时候, 对其中一个对象赋值不会引起另一个对象的同步改变
二者的关系
exports 本质上是 module.exports 的一个引用, 这就说明了为什么这两个对象的属性会同步改变, 并且当我们以module.exports = myFunc()
或者 exports = myFunc(){}
这样的方式赋值的时候, 另一个对象不会同步改变的原因: 因为原本二者指向同一个对象, 直接对指针赋值,其实是改变了指针的指向,而不是改变指针原本指向的对象上的属性,现在这样赋值就破坏了原本的相同引用的关系
它们从哪里来, 我为什么能直接用?
在一个模块的代码被编译的时候, 用户写的代码会被一个包装函数给包起来:
1 | (function(exports, require, module, __filename, __dirname) { |
而包装函数被调用的过程看起来像是这样的(来源官方文档):
1 | function require(/* ... */) { |
由此也可理解 exports 和 module.exports 的关系
为什么要有 exports 呢
既然 exports 是 module.exports 的一个引用, 那么我直接对 module.exports 进行操作不就好了吗, 为什么我还需要 exports 呢?
答案是
- 为了方便性
- 以及写出更清晰简洁的代码(个人看法, 毕竟代码是写给人看的)
nodejs 官方文档给出的解释是:
It allows a shortcut, so that module.exports.f = … can be written more succinctly as exports.f = …
export for ES6
1 | export * from 'lib1' |
◉ End.
参考资料:
如博文有叙述不妥以及不准确的地方, 望各位看客不吝赐教, 感谢.