module.exports 与 exports

241 阅读3分钟

本人是一个前端小白,之前一直弄不懂 module.exports 跟 exports 的区别以及用法,因为看到许多别人的代码,这两个的用法各种各样,比如说有:


exports.something = something;              //a

module.exports.something = something;       //b

exports = something;                        //c

module.exports = something;                 //d

exports = module.exports = something;       //e

//what?????一脸蒙蔽,,,,在这里我只总结了我所能想到的一些用法而已,不知道还有没有其他我不知道的用法
//题外话,如果就把这些东西放在一起对于像我这样的小白来说也很难说出个1234,何况es6还来个export混淆视听。。。

因为最近在看一些nodejs的教程,发现这个东西经常出现,所以弄懂他就显得刻不容缓了。我觉得弄懂这两个东西最重要的就是理解一下三点:

  1. module.exports 和 exports 都指向同一内存地址的一个空对象 {}
  2. module.exports 的指向改变时是不会对 exports 的指向产生任何影响的,反之亦然
  3. require() 返回的是 module.exports 而不是 exports

如果你明白了这三点的话,无论是它俩的用法还是区别都能如数家珍;关于1,2两点我们可以写一个简单的 demo 来证明一下:


console.info(module.exports)
//output: {}

console.info(exports)
//output: {}

console.info(module.exports === exports)
//output: true

exports.a = 1;
console.info(module.exports)
//output: {a:1}

module.exports.a = 4;
console.info(exports)
//output: {a:4}

module.exports = { a: 1 };
console.info(exports)
//output: {}

exports = { a: 1 };
console.info(module.exports)
//output: {}

从上面的例子可以知道他们初始确实都指向同一个内存地址,这块内存上储存着一个空对象,并且当其一指向改变时是不会影响另一个的指向的。而第三点也很好证明,首先我们创建一个 a.js,我们在其中用 exports 暴露模块并在 吧,b.js 中引用:


//a.js

exports = { num: 1 };


var a = require('./a.js');
console.info(a);
//output:{}

由第2点可知我们在 a.js 中暴露模块时改变了 exports 的原始指向,导致 module.exports 的指向还是一个空对象,所以在 require 引用时得到的是原始的空对象。

现在我们只是弄清楚了这两者之间的异同,那么究竟弄清除这些有什么用呢,这两者都是 nodejs 提供给我们用于暴露模块以便外部引用的工具,既然是工具那就得使用它,可你应该怎么使用它呢?

明白了第1点的我们应该就知道这两者的初始值都是一个空对象,那么如果你有一个模块需要通过这两者其中的一个暴露出去,当你要覆盖原始值指向的内存地址时最好用d、e这两种写法,c的这种写法 require 时是有问题的,不改变指向的话a、b两种都行哈,因为操作的都是同一个对象,所已在 require 时是都能通过 module.exports 取到的。。。

以上这些都是我个人的愚见,有错误的地方请多指教,说实话,写这篇blog是因为怕自己忘记,写给自己看的。。。。所以写得很随便,,,,,,应该不会有人看到吧。。。。