全局执行上下文预编译在脚本执行前进行,核心是创建go对象、收集var/function声明、设初始值(undefined/函数体);函数声明优先于同名变量声明,但执行阶段赋值会覆盖预编译值。

全局执行上下文的预编译,是 JavaScript 引擎在代码真正执行前做的“准备工作”,核心就三件事:建对象、收声明、设初始值。它不运行代码,只梳理结构,为后续执行铺路。
预编译发生在什么时候
页面加载完成、脚本开始执行前的瞬间。此时 JS 引擎已完成语法检查(比如 var 写成 vra 会直接报错中断),紧接着就进入预编译阶段。
预编译三步走:GO 对象怎么建出来的
全局预编译围绕一个核心对象展开——GO(Global Object,在浏览器中就是 window)。它的生成分三步:
- 创建空的 GO 对象:
GO = {} - 扫描所有 var 声明,把变量名作为属性加入 GO,值统一设为 undefined(注意:只处理声明,
var a = 1的赋值不参与) - 扫描所有 function 声明,把函数名作为属性加入 GO,值是整个函数体;若同名函数多次出现,后声明的会覆盖前声明的
变量和函数谁优先?函数声明优先级更高
当变量和函数同名时,函数声明会先被录入 GO,之后变量声明再进来,但不会覆盖已有的函数——除非后续执行阶段重新赋值。
例如:
var a = 1;function a() {}
console.log(a); // 输出 1,不是函数
原因:预编译阶段 GO.a 先被设为函数体;但执行阶段 var a = 1 这行代码会把 GO.a 改成 1,覆盖了函数。
执行阶段才是真正的“赋值时刻”
预编译只是搭架子,所有 = 赋值、函数调用、表达式计算,都在预编译之后按顺序执行。此时 GO 中的值才真正被写入或修改。
简单说:预编译决定“有哪些东西可用”,执行阶段决定“它们是什么值”。











