作者:_我的最愛 | 来源:互联网 | 2023-09-06 13:25
1. 原理解析
NodeJS中使用了CommonJS的模块化标准,Node内部提供一个Module构建函数。所有模块都是Module的实例。每个模块内部,都有一个module对象,代表当前模块。而这个module对象中,就存在一个成员 exports
,该成员也是一个对象。也就是说,如果你需要对外导出成员,只需要把导出的成员挂载到 module.exports
上就可以了,最终module对象中会执行 retrun module.exports
将挂载的值返回给require的对象。
var module = {exports: {}
}
所以,原理是你是可以这么写的
function add(a, b) {return a + b
}module.exports.add = add
运行结果也无报错
但是你会发现,这样做的话,每次都需要写那么长的一截 module.exports.xxx
,很麻烦,于是就引入一个 exports 变量 (注意:就只是个变量名,不是module里面的那个exports对象)
var exports = module.exports;
如果是学过指针或者对数据结构比较熟悉的同学,一看到这个代码就明白是怎么一回事了,它是一个引用传递,就只是把 exports 指向了和module.exports 的同一块内存空间。
因此,exports变量就可以向exports对象中添加方法或属性
也就是说exports.add
与 module.exports.add
的作用是一样的。
而当你操作exports变量指向其他空间的时候,它就与exports对象断联了,比如说: exports = add
,这个语句是直接将exports指向了add 方法的返回值
2. 用法区别
一般来说,导出多个成员可以沟通过使用多个 exports.xxx = xxx
或者使用一个 module.exports = {}
的方式来实现,而导出单个成员时使用module.exports = xxx
。
你肯定很疑惑为什么说导出单个的时候使用 module.exports = xxx
?人家做exports变量不就是方便你使用的吗?你怎么辜负别人的好心?
举个例子你就明白了
还是上面的那个两数相加的案例,和上面不同的是,我直接写了module.exports = add
而不是 module.exports.add = add
function add(a, b) {return a + b
}module.exports = add
接下来我在另外一个文件中,导入这个文件,并调用它的add方法。
const wantAdd = require('./module')
console.log(wantAdd(1,2))
输出的结果为 3
而如果改成了 exports.add = add
的方式导出的话
const wantAdd = require('./module')
console.log(wantAdd.add(1,2))
输出结果同样为3
那有什么不同呢? 聪明的你一定发现了,使用 module.exports = xxx
的时候,我调用 add 方法是直接通过 wantAdd(1, 2)
来实现的;而使用 exports.add = add
的时候,调用add方法需要通过 wantAdd.add(1, 2)
来实现的。
原理就是由于module.exports = xxx
是直接导出了 exports对象,也就说exports对象就是add方法;而exports.add = add
相当于 module.exports.add = add
,是在 exports 中新加了一个变量去指向 add 方法,所以你用wantAdd变量接收exports对象时,还需要调用 add 变量去使用到 add方法。
所以在导出单个的时候,使用 module.exports
会更方便些。
总结
exports 与 module.exports 本是同根生,在用法上稍稍不同,原理上也比较简单易懂。exports.xxx = xxx
在传递多个对象的时候,写法看起来优雅一些,算是一种快捷方式。若你实在是感受不到 exports 的好处或者分不清 exports变量与module.exports的区别,那你就使用module.exports 就好了,绝对不会有问题的。