CommonJS模块通过自执行函数封装实现作用域隔离,每个文件拥有独立module实例,仅module.exports可被外部访问,天然避免全局污染与命名冲突。

CommonJS 模块系统通过函数封装实现作用域隔离,每个 .js 文件在 Node.js 中运行时,都会被自动包裹进一个私有函数作用域里,而不是直接挂在全局上。这意味着模块内的 var/let/const、函数声明、内部变量全部仅在该模块内有效,天然不污染全局作用域,也不受其他模块干扰。
模块被自动封装成函数作用域
Node.js 在加载每个模块时,实际执行的是类似这样的结构:
(function (exports, require, module, __dirname, __filename) {
// 你写的模块代码在这里执行
const secret = 'only in this module';
function helper() { return secret; }
module.exports = { publicFn: helper };
})();
这个自执行函数就是模块的“边界”——它创建了独立的作用域,所有顶层声明都只属于这个函数内部,外部完全访问不到 secret 或 helper,除非显式导出。
module.exports 是唯一对外出口
模块内部可以自由定义任意变量和逻辑,但只有赋值给 module.exports(或其别名 exports)的内容才会被其他模块拿到:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
-
const internal = 'hidden';→ 外部不可见 -
exports.visible = 'ok';→ 等价于module.exports.visible = 'ok' -
module.exports = { fn() {} };→ 替换整个导出对象,此时exports不再起作用 -
exports = { a: 1 };→ ❌ 无效,因为只是改了局部变量 exports 的指向,不影响 module.exports
每个模块拥有独立的 module 实例
即使两个文件都写 module.exports = {},它们的 module 对象也是完全不同的实例,互不影响:
-
module是当前模块的上下文对象,包含id、filename、exports等属性 - 同一文件多次
require,返回的是缓存的module.exports,不会重复执行模块代码 - 不同文件的
module彼此隔离,各自维护自己的exports和内部状态
与全局作用域彻底解耦
模块中没有显式声明为全局的变量(比如没加 window.xxx 或 global.xxx),就不会泄漏到全局:
-
var x = 1;→ 只在模块函数内有效 -
this.y = 2;→ 指向当前module.exports,不是 global -
global.z = 3;→ 才真正挂到全局,但这是主动行为,不是模块机制导致的
这种设计让模块像一个个封闭盒子,彼此之间只能靠明确的导入导出通信,从根源上避免命名冲突和意外覆盖。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










