在 type="module" 脚本中,var 声明的变量仅限模块作用域内访问,不会挂载到全局对象(如 window)上,因其顶层作用域是模块的 lexical environment 而非 global environment record。

因为在 type="module" 脚本中,整个模块默认处于严格模式且拥有独立的**模块作用域**,var 声明的变量不会被挂载到全局对象(如 window 或 globalThis)上。
模块脚本天然隔离全局污染
HTML 中通过 <script type="module"></script> 加载的脚本,其执行环境不是全局作用域,而是模块作用域。即使你写:
var foo = 'hello'; console.log(window.foo); // undefined
这里的 foo 只存在于该模块的顶层作用域内,不会成为 window 的属性。这和传统 <script></script>(非 module)的行为截然不同——后者中顶层 var 会自动变成全局变量。
var 的作用域范围没变,但“顶层”已不是全局
var 本身仍具有函数作用域(或模块顶层作用域),它不会产生块级作用域,但它也不会突破模块边界:
- 在普通脚本中,顶层
var x→window.x可访问 - 在模块脚本中,顶层
var x→ 仅本模块内可访问,window.x不存在
本质是规范定义:模块不共享全局词法环境
根据 ECMAScript 规范,每个模块都有自己的 Module Record,其顶层声明绑定在模块的 Lexical Environment 中,而非 global environment record。因此:
-
var、let、const在模块顶层都只属于该模块 - 想暴露给其他模块,必须显式
export - 想挂到全局对象上,必须手动赋值,例如
window.myVar = value
对比验证示例
新建两个文件:
script.js(普通脚本):
var a = 1;
console.log('in script.js:', window.a); // 1
module.mjs(或 .ts 编译为 module):
var b = 2;
console.log('in module.mjs:', window.b); // undefined
console.log('in module.mjs:', b); // 2(仅模块内可见)
引入方式:
<script src="script.js"></script><script type="module" src="module.mjs"></script>
结果清晰显示:模块内的 var 不污染全局。











