先看个例子 A:
let a={name:"chen"}
let b= a //b{name:"chen"}
b 浅拷贝了 a,可以说 b 是 a 的引用,因为它们指向了同一个内存地址,它们相互影响。但是!当 b=function bb(){xxx} 后,b就不指向 a 的内存地址了,也就是说,b 不再是a 的引用了,从这之后,b的改变不会影响a,a的改变(a 永远是一个对象)也不会影响b
exports:
(1)它最初是一个可以添加属性的空对象。
(2)它是 module.exports 的全局引用。
(3)如例子 A 所说,当用其他对象、函数或变量给 exports 赋值,那么 exports 就不再是 module.exports 的引用,换句话说,会导不出来所需要的函数、变量,导致报错。
如例子 B:
currency.js:
function oneToTwo() {
console.log("222")
}
function oneToThree() {
console.log("333")
}
//这里将一个函数方法赋值给 exports,
//导致 exports 不再是 module.exports 的引用
exports=oneToTwo
testCurrency.js:
let Currency=require("./currency")
//因为导出的是 module.exports 而不是 export,
//而不再是 module.exports 引用的 exports 没有改变 module.exports 的值,
//所以 module.exports 的值仍为初始值 {}
console.log(Currency) // {}
module.exports:
(1)程序导出的永远是 module.exports
(2)如果你创建了 既有 exports 又有 module.exports 的模块,那它会返回 module.exports
(3)如果 exports 不再是 module.exports 的引用,使用如下方法,重新保持两者的连接
module.exports=exports=oneToTwo
或者
exports=module.exports=oneToTwo
注意:当你在 currency.js(上面提到的文件)写
exports.oneToTwo=oneToTwo
的时候,这个 exports 不是 exports,不是做 module.exports 引用的那个 exports,而是 module.exports,这个 exports.oneToTwo 是 module.exports.oneToTwo 的简写。
是不是很搞,很烦?我也觉得很搞,那么问题来了:
为什么要拿一个 exports 来做 module.exports 的引用?而不是直接使用 module.exports ?
我现在也还未明白,看了这篇博文(https://cnodejs.org/topic/52308842101e574521c16e06),原话是说「其实,当我们了解到原理后,不难明白这样的写法有点冗余,其实是为了保证,模块的初始化环境是干净的。同时也方便我们,即使改变了 module.exports 指向的对象后,依然能沿用 exports的特性」
最后用官方的一句话,简述两者区别:
If you want the root of your module’s export to be a function (such as a constructor) or if you want to export a complete object in one assignment instead of building it one property at a time, assign it to module.exports instead of exports.
如果希望模块导出的是其他对象、函数或变量,那么用 module.exports 而不是 exports
欢迎关注本公众号:
(完)
网友评论