使用exports和module.exports导出变量
exports 变量是在模块的文件级作用域内可用的,且在模块执行之前赋值给 module.exports。
exports.name = '前端小兵'
虽然只用了exports导出name变量,但最终的效果类似于 module.exports.name = exports.name。
我们知道js是顺序执行的,所以我们在导出变量的时候,如果遇到相同变量的话,下面的代码是会覆盖上面的相同变量赋值。
module.exports.name = '前端小兵2' exports.name = '前端小兵'
根据上面的规则,可以知道最后导出的变量name的值是“前端小兵”。
不能直接将变量赋值exports
exports = { hello: false }; // 不导出,仅在模块中可用。
也就是上当我们使用exports直接导出值的时候,是不会将值赋给module.exports的,所以上面的代码在require的时候不会有任何变量导出。
注意书写顺序
module.exports.name = '前端小兵' module.exports = { hello: false } // 结果: { hello: false } module.exports = { hello: false } module.exports.name = '前端小兵' // 结果: { hello: false, name: '前端小兵' }
可以看到书写顺序对于导出值的影响,module.exports 加一个变量,是会叠加到导出内容的,但对于直接将对象值赋值给module.exports的行为,是会直接覆盖之前的内容的。
require导入的模拟代码
我们来看看require在执行导入的过程中,module.exports和exports都做了哪些操作。
function require(/* ... */) { const module = { exports: {} }; // 也就是模块自带一个module.exports ((module, exports) => { // 模块代码在这。在这个例子中,定义了一个函数。 function someFunc() {} exports = someFunc; // 此时,exports 不再是一个 module.exports 的快捷方式, // 且这个模块依然导出一个空的默认对象。 module.exports = someFunc; // 此时,该模块导出 someFunc,而不是默认对象。 })(module, module.exports); return module.exports; }