CommonJS 模块系统
一、每个 CJS 文件都被包装成函数
1 | (function (exports, require, module, __filename, __dirname) { |
包装带来:
- 作用域隔离:顶层变量不会污染全局。
- 注入五个参数:
exports、require、module、__filename、__dirname是形参,不是全局变量,每个模块独立。 - 导出通道:
module.exports作为参数传入,模块代码往它上面挂东西。
二、module、exports、module.exports 的关系
1 | const module = { exports: {} }; |
- 挂属性安全:
exports.a = 1等价于module.exports.a = 1,因为操作同一对象。 - 整体赋值危险:
exports = { a: 1 }断开引用,module.exports还是空对象,导出失效。 - 整体替换正确写法:
module.exports = { a: 1 }。 - Node 最终导出的是
module.exports的值,不是exports变量。 module对象本身不暴露给使用者,require拿不到module.id、module.filename等。
三、require 的完整流程
1 | 1. 解析路径(补扩展名、找 index.js、查 node_modules) |
重点:
- 缓存存的是整个
module对象,命中时取.exports。 - 返回的是
module.exports的值,不一定是对象(可能是函数、数字、字符串等)。 - 同一模块多次
require,代码只执行一次,返回同一引用。 require返回的不是module对象本身。
每个 CJS 文件被包成函数执行,module.exports 是唯一导出通道,exports 只是它的初始别名;require 查缓存、执行包装函数、返回 module.exports 的值。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 YianNotes!

