Node 中 exports 与 module.exports 有什么区别(下)

在之前的文章中,粗略谈到了Node 中 exports 与 module.exports 有什么区别,本文将展开讨论,更详细地补充两者的区别。

一、两者的关联本质

在JS文件启动时,Node.js 开始执行文件,会给这个文件内生成一个 exports 和 module 对象,而module又有一个 exports 属性。两者都指向一块内存区域.

二、require()加载模块

Node.js依然遵循 CommonJS 规范,使用 require 关键字来加载模块。
而要区分两者,用内存指向的方式更好理解:exports 只是 module.exports的引用,辅助后者用于添加内容。

//test.js
let a = 'Hello Wolrd!';
console.log(module.exports); //能打印出结果为:{}
console.log(exports); //能打印出结果为:{}
exports.a = 'Hello FuZhou!'; //这里 exports 将 module.exports 的内容给改成 {a : 'Hello FuZhou!'}
exports = 'Bye Bye!'; //这里将 exports 的指向改变

//exe.js
const a = require('/test');
console.log(a) // 打印为 {a : 'Hello FuZhou!'}

由此说明,require导出的内容是module.exports指向的内存块内容,并不是exports指向的内存块内容。

三、官方文档中exports的应用

Node 中 exports 与 module.exports 有什么区别(下)_第1张图片
官方文档中exports的应用

在源码中,经常可以看到以下写法:

exports = module.exports = somethings

上面的代码其实等价于:

module.exports = somethings
exports = module.exports

原理:当 module.exports 指向新对象时,exports 断开了与 module.exports 的引用;所以通过 exports = module.exports 让 exports 重新指向 module.exports 。

四、小结

Node.js 认为每个文件都是一个独立的模块。
如果包有两个文件,假设是“a.js” 和“b.js”。如果“b.js” 需要使用“a.js” 的功能,则“a.js” 必须要通过给 exports 对象增加属性来暴露这些功能:

// a.js
exports.verifyPassword = function(user, password, done) { ... }

完成这步后,所有需要“a.js” 的都会获得一个带有“verifyPassword” 函数属性的对象:

// b.js
require(‘a.js’) // { verifyPassword: function(user, password, done) { ... } } 

如果想直接暴露这个函数(a.js),而不是让它作为某些对象的属性,则可以通过覆写 exports 来达到目的:

// a.js
module.exports = function(user, password, done) { ... }

但是需要注意的是,绝对不能把它当做一个全局变量

总之,“module.exports” 和“exports” 之间的区别经常会使 Node.js 新手踩坑。
但只要记住的是:把“exports” 当做 module 对象的一个属性。

你可能感兴趣的:(Node 中 exports 与 module.exports 有什么区别(下))