exports:导出
- Node中是模块作用域,默认文件中所有的成员只在当前模块有效
- 对于希望可以被其他模块访问到的成员,我们需要把这些公开的成员都挂载到exports接口对象中就可以了
先理解这句话
- 每个模块中都有一个module对象,module对象中有一个exports对象
我们可以把需要导出的成员都挂载到module.exports接口对象中,但书写很麻烦module.exports.xxx = xxx
,所以node为了方便书写,同时在每一个模块中都提供了一个成员叫exports
exports和module.exports是等价的
console.log(exports === module.exports)
输出的结果:true
同理:
exports.foo = 'haha'
module.exports.foo = 'haha'
这两条是一样的
那么问题来了?
当一个模块需要到处单个成员的时候,为什么必须使用module.exports = xxx
而不能使用exports = xxx
呢?
我们用代码来解释:
代码默认最后:return module.exports
//module.exports指向一个对象 开辟一个内存空间
let module.exports = {}
//exports和module.exports指向同个对象
let exports = module.exports
//此时对象 foo = 'hello'
exports.foo = 'hello'
//此时 'world'把'hello'替换了 foo = 'world'
module.exports.foo = 'world'
//exports重新指向新的对象 开辟另一个内存空间 和module.exports无关了
exports= {}
//因为和module.exports不指向同一个对象 所以不影响
exports.foo = 'hello'
module.exports.mm = 123
结果输出的是:{foo: 'world', mm: 456}
如果还不理解的话,看下图分析:
前四行代码:
第五行到最后一行代码:
总结
我们要知道一句话,最终代码默认是return module.exports
所以一旦exports = '任何内容',
就与module.exports无关了,接下来exports.xxx
都没用,都不会输出。但是一旦重新exports = module.exports
,就会重新建立引用关系。
下面做个例子:
// {foo: bar}
exports.foo = 'bar'
// {foo: bar, a: 123}
module.exports.a = 123
// exports !== module.exports
// 最终 return 的是 module.exports
// 所以无论你 exports 中的成员是什么都没用
exports = {
a: 456
}
// {foo: 'haha', a: 123}
module.exports.foo = 'haha'
// 这个只是混淆你的 不影响
exports.c = 456
// 重新建立了和 module.exports 之间的引用关系了
exports = module.exports
// 由于在上面建立了引用关系,所以这里是生效的
exports.a = 789
最终输出结果是:{foo: 'haha', a: 789}
如果结果和你的一样,证明你就已经理解了!