es6模块执行上下文与全局执行上下文是并列的独立顶层环境:模块内let/const/class/function不挂载全局对象、默认严格模式、this为undefined、存在tdz;全局脚本中var声明挂window、this指向全局对象、var有变量提升。

ES6 模块执行上下文和全局执行上下文是两种不同生命周期、作用域规则与变量绑定机制的执行环境,核心区别不在“有没有上下文”,而在“如何创建”“绑定谁”“能否提升”“this 怎么指”。
模块执行上下文是独立的顶层作用域
每个 .js 文件被作为 ES6 模块(type="module" 或通过 import/export 触发)加载时,会创建一个**独立的模块执行上下文**,它不是全局上下文的子集,而是与之并列的顶层环境。
- 模块内顶层声明的
let、const、class、function不会挂载到window(浏览器)或globalThis上; - 模块代码默认处于严格模式,即使没写
"use strict"; - 模块有自己隐式的词法环境(Lexical Environment),其外部引用链指向
globalThis,但自身不污染它。
全局执行上下文仍存在,但模块不共享它
传统脚本(<script></script> 无 type="module")仍进入全局执行上下文:变量用 var 声明或直接赋值会成为 window 属性,this 指向 window。
- 全局上下文在页面加载时创建,生命周期贯穿整个文档;
- 模块上下文在模块解析完成、首次执行前创建,生命周期随模块实例存在;
- 两者共存但隔离:模块里访问不到全局脚本中用
var声明的变量(除非显式挂到window),反之亦然。
变量提升与初始化行为完全不同
全局上下文对 var 有变量提升(hoisting)且初始化为 undefined;模块上下文对 let/const 也有“提升”,但处于**暂时性死区(TDZ)**,访问会报 ReferenceError。
- 全局脚本:
console.log(a); var a = 1;→ 输出undefined; - 模块脚本:
console.log(b); let b = 2;→ 报错ReferenceError: Cannot access 'b' before initialization; - 模块中
import绑定也是 TDZ 行为,import声明不可条件化、不可重复、不可删除。
this 的绑定方式有根本差异
在全局执行上下文中,顶层 this 指向 window(浏览器)或 global(Node.js);但在模块执行上下文中,顶层 this 的值是 undefined(严格模式强制结果)。
- 这意味着
console.log(this === window)在普通脚本中为true,在模块中为false(实际是this === undefined); - 函数内部的
this行为不受影响,但模块顶层的this不再是全局对象——这是模块封装性的重要保障。











