CommonJS
Node应用是由模块组成的,采用的是CommonJS模块规范。
- 根据规范一个文件就是一个模块,有自己单独的作用域,在一个文件中定义的变量,函数,类都是私有的,对其他的文件不可见。
- 根据规范,每个模块内部,module代表当前的模块,这个变量是一个对象,他的exports属性是对外的接口。
- module.exports用于输出文件对象,require用于加载模块。
node在执行一个文件的时候会在文件内部生成exports对象和module对象,module对象又一个属性为export
当我们在文件中打印下两者是否相等可以看到结果为true
console.log(exports === module.exports)
这证明了两个对象是指向的同一个内存地址,同时也只有module.exports对象返回了
其实可以这样理解初始化一个文件的时候node帮我们做了以下这件事:
const module={
exports:{}
}
const exports=module.exports
node应用在被执行前会被包装一下
(function(exports,require,module,__filename,__dirname){
...
})
在进行头尾封装之后,各模块之间进行了作用域的隔离,避免了全局变量实现了:
- 保持了顶层的变量(用var和const等定义的)作用在模块的范围内,而不是全局的
- 提供了一些模块特定的变量
- 从模块中导出值module和exports对象
- 包含了模块绝对文件名(__filename)和目录路径(__dirname)
总结
- exports是module对象的一个属性,在初始化的时候module.exports和exports指向了同一个内存地址
- 模块导出用的是module.exports,exports只是对这个地址的一个引用