exports 与 module.exports 的区别
exports与module.exports的作用就是将方法或者是变量暴露出去,以便给其他模块调用,再直接点,就是给其他模块通过require()的方式引用。
那么require()一个模块时,到底做了什么呢?下面大概展现了require()的伪代码实现:
function require(/* ... */) { const module = { exports: {} }; ((module, exports) => { // Module code here. In this example, define a function. // function someFunc() {} // exports = someFunc; // At this point, exports is no longer a shortcut to module.exports, and // this module will still export an empty default object. // module.exports = someFunc; // At this point, the module will now export someFunc, instead of the // default object. })(module, module.exports); return module.exports; }
由此可以看出:
- module.exports默认指向一个空对象{}
- exports在默认情况下是指向module.exports的引用
- require()返回的是module.exports而不是exports
所以,如果是通过exports.test = function() {} 的形式暴露出去,无论是使用exports还是使用module.exports,在功能上并没有什么差别;但是如果是通过exports = function() {} 的形式暴露出去,结果往往会出乎意料。从伪代码中可知,exports对象是通过形参的方式传入的,直接赋值形参会改变形参的引用,但是不会改变作用域外的值,也就是说module.exports原来的值是什么,现在还是什么,不会有任何改变,而require()方法最终返回的是module.exports,所以结果可想而知。
// 文件1.js exports = function () { console.log('exports') } // 文件2.js var test = require('./1'); console.log(test); // 结果是module.exports的默认值,也就是空对象{}