全局执行上下文启动时,JavaScript引擎创建全局对象(GO)作为顶层容器,它在浏览器中是window、Node.js中是global,ES2020起统一用globalThis访问;GO在解析阶段初始化,挂载var和function声明,但不挂载let/const;GO即全局VO,var声明等价于向GO添加属性,但默认不可删除。

全局执行上下文(Global Execution Context, GEC)启动时,JavaScript 引擎会立即创建一个全局对象(Global Object, GO),它是整个 JS 环境的顶层容器,所有全局声明的变量、函数、内置构造器(如 Date、Array)、全局方法(如 setTimeout)都作为它的属性存在。
全局对象在不同环境中的具体表现
全局对象不是抽象概念,而是真实存在的运行时对象,其具体身份取决于宿主环境:
-
浏览器环境:GO 就是 window 对象(注意:在严格模式下,
this在全局中为undefined,但window仍可访问);window.window === window为true,即它拥有自引用属性。 -
Node.js 环境:GO 是 global 对象,不暴露
window;global.global === global同样成立。 - 统一访问方式:ES2020 起推荐使用 globalThis —— 它在所有环境都指向当前环境的 GO,无需判断运行上下文,是真正跨平台的全局对象引用。
全局对象与变量提升(Hoisting)的关系
GO 的初始化发生在代码执行前的“解析阶段”,而非执行阶段。此时引擎扫描全部顶层代码,将 var 声明和函数声明挂载到 GO 上,但仅做“注册”,不赋值(var 初始化为 undefined,函数则直接绑定函数对象):
-
var a = 10;→ GO 中新增属性a,初始值为undefined;执行到该行时才赋值为10。 -
function foo() {}→ GO 中立即添加foo属性,值为函数对象(可立即调用)。 -
let b = 20;或const c = 30;不挂载到 GO,它们属于词法环境(LexicalEnvironment)管理,不存在变量提升,也不可通过window.b访问。
全局对象是变量对象(VO)的具体实现
在全局执行上下文中,“变量对象”(Variable Object, VO)这个抽象概念就由全局对象(GO)实体承担。也就是说:
- 你通过
var声明的全局变量,本质就是给 GO 添加可枚举属性; -
window.myVar = 'ok'和var myVar = 'ok'在效果上等价(非严格模式下); - 但需注意:
delete window.myVar可以删除该属性(若未被设为不可配置),而var声明本身不能被删除 —— 这是因为var创建的属性默认configurable: false(在非严格模式下部分浏览器行为略有差异,但现代引擎已趋一致)。
常见误区与注意事项
虽然 GO 是顶层作用域载体,但开发者常忽略几个关键事实:
-
GO 不等于 this(在某些场景):全局执行上下文中,非严格模式下
this === window(浏览器),但严格模式下this为undefined,而window依然可用 —— 二者语义不同。 -
iframe 有独立 GO:每个 iframe 拥有自己的
window,彼此隔离;跨 frame 访问需显式通过iframe.contentWindow。 -
模块脚本(type="module")无隐式 GO 绑定:ES 模块顶层声明不会自动挂载到
window,即使用了var,这也是模块作用域封闭性的体现。 -
避免污染 GO:随意向
window添加属性易引发命名冲突,现代开发应优先使用模块、IIFE 或globalThis显式控制作用域边界。

















