这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
前言
Node的模块加载是采用的CommonJS规范,区别于AMD的异步加载,CommonJS是同步加载,因为Node代码一般是部署在服务器上,它依赖的模块也是存在服务器上,所以相当于本地加载模块,加载速度很快,采用同步加载不影响等待时间。
CommonJS内部采用require指令去加载模块,采用module.exports或者exports去导出模块,今天来看看这两个导出指令有何异同。
module.exports
node中,每个文件都是一个模块,一个模块里面有module对象,然后它有个属性,exports, 代表的是对外输出的接口。需要对外输出的值都赋值到这个属性下面,就可以通过require访问到。
exports
为了每次都无需写module.这个指令,CommonJS提供了便捷入口,可以只需写exports 代表module.exports。这是一个便捷指令。
异同
我们可以来打印来看看
新建一个index.js
console.log(module.exports) // {}
console.log(exports) // {}
console.log(module.exports === exports) // true
执行node index.js,可以看到打印的都是{}, 这说明默认值是{}, 而且他们是全相等的,说明它们其实是指向同一个对象的。
我们先来看看它们的用法:
exports的用法
main.js
exports.name = '答案cp3'
use.js
const obj = require('./main.js')
console.log(obj.name) // 答案cp3
module.exports的用法
main.js
module.exports.name = '答案cp3'
use.js
const obj = require('./main.js')
console.log(obj.name) // 答案cp3
这样使用是没有问题的,都能打印出答案cp3。
我再换一种写法,大家就能看出它的区别了
exports的用法
main.js
exports = {
name: '答案cp3'
}
use.js
const obj = require('./main.js')
console.log(obj) // {}
console.log(obj.name) // undefined
module.exports的用法
main.js
module.exports = {
name: '答案cp3'
}
use.js
const obj = require('./main.js')
console.log(obj) // { name: '答案cp3' }
console.log(obj.name) // 答案cp3
可以看到,
- 第一个
exports的用法,打印出来的是undefined - 第二个
module.exports的用法,打印出来的是答案cp3
为什么会这样?不是应该都一样吗?
我们再来看看一个例子:
main.js
exports.a = {
name: '答案cp3'
}
module.exports = {
name: '答案cp3'
}
use.js
const obj = require('./main.js')
console.log(obj) // { name: '答案cp3' }
这个例子,只打印了{ name: '答案cp3' },exports.a这个属性被忽略了。
好的,来总结一下以上例子。
-
module对象在初始化时给自己加上exports属性,并赋值{}, 另外声明一个exports变量,然后把exports属性赋值给它。类似于
var module = { exports: {} } var exports = module.exports -
导出模块都是使用的
module.exports,而不是exports。所以一旦我们给
exports或者module.exports重新赋值,相当于切断了另一方的引用。导致二者不能关联起来。比如:
var module = { exports: {} } var exports = module.exports // 此时给exports赋值 exports = { name: '答案cp3' } console.log(module.exports) // 还是空对象所以我们
- 要么就只用
module.exports这个属性,不用exports - 要么就只给
exports添加属性,不要重新赋值
- 要么就只用
总结
module.exports初始值为一个空对象{}exports是指向的module.exports的引用- 导出的,也就是
require导入的, 都是指向module.exports属性 - 对
exports或者module.exports重新赋值,就切断了双方的引用关系