ES模块通过严格模式和隐式函数包装实现作用域隔离,顶层声明不污染全局对象,仅能通过import/export显式通信,CommonJS虽机制不同但效果一致。

JavaScript中模块作用域与全局作用域天然隔离,核心在于ES模块(import/export)默认启用严格模式且自动包裹在私有作用域中,不污染全局环境。
模块代码自动运行在隐式函数作用域内
每个ES模块文件(如 utils.js)在加载时,会被引擎视为被一个封闭的、不可见的函数包装过。这意味着:
- 模块顶层声明的变量、函数、类(如
const a = 1;或function foo(){})仅在该模块内部可见 - 即使使用
var声明,也不会提升到全局作用域,而是绑定到模块环境记录(Module Environment Record) - 模块中直接写
this指向undefined(严格模式),而非window或globalThis
全局对象不再接收模块顶层声明
在非模块脚本(如通过 <script></script> 直接引入)中,顶层 var 或函数声明会成为全局对象的属性(例如 window.a)。但模块完全不同:
-
var x = 42;在模块中不会让globalThis.x存在 - 显式挂载才会影响全局,比如
globalThis.myLib = { ... };或window.MyClass = class {...}; - 浏览器中
import的模块与<script type="module"></script>同属同一套模块系统,共享该隔离规则
import 和 export 是唯一标准通信接口
模块之间或模块与外部交互,只能通过显式导入导出,无法靠作用域链隐式访问:
-
export const PI = 3.14;仅表示“可被其他模块通过import获取”,不等于“定义在全局” -
import { PI } from './math.js';是静态解析的绑定,不是拷贝值,也不是动态查全局对象 - 即便用
export default,导入时仍需命名(如import calc from './calc.js'),不会自动注册为全局变量
CommonJS 和 ES 模块的隔离逻辑一致但机制不同
Node.js 中的 CommonJS(require/module.exports)也隔离作用域,但实现方式是显式包装:
- 每个
.js文件被读取后,实际执行的是类似(function(exports, require, module, __filename, __dirname) { ... })的函数 - ES模块则由语言规范强制隔离,无需运行时包装,更轻量、更静态、支持tree-shaking
- 两者都使
global(Node)或window(浏览器)保持干净,除非主动赋值
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











