2021-11-23 20:34:04
JavaScript 引擎执行代码的过程可分为语法分析、编译、执行三个阶段,其核心机制围绕执行上下文的创建(包括变量对象、作用域链、this 指向)展开。以下是详细步骤说明:
一、语法分析阶段每进入一个新运行环境(如全局、函数、eval),引擎会创建对应的执行上下文,包含以下核心操作:
1. 创建变量对象(VO)创建 arguments 对象(记录参数值)。
处理函数声明和变量声明:
函数声明:直接初始化函数对象(函数提升优先于变量提升)。
变量声明:初始化为 undefined(赋值操作在执行阶段进行)。
全局环境:指向 window(浏览器)或 global(Node.js)。
函数调用:
作为对象方法调用时,指向调用对象(如 obj.method() 中的 obj)。
使用 new 调用时,指向新创建的对象。
箭头函数继承外层 this。
通过 call/apply/bind 显式绑定。
类构造函数:指向新实例对象。
激活变量对象:将编译阶段的 VO 转为活动对象(AO),完成变量赋值和参数传递。
AO 组成:AO = VO + 函数参数 + arguments。
示例:
function foo(a) { var b = 2; function c() {}}foo(1); // 执行时 AO: { a: 1, b: 2, c: function, arguments: { 0: 1, length: 1 } }执行代码:按顺序执行语句,通过作用域链访问变量。
销毁上下文:函数执行完毕后,其执行上下文(含作用域链和 AO)被销毁,但闭包会保留变量对象。
编译阶段:
全局环境创建 example 函数。
调用 example(1) 时,创建函数执行上下文:
VO: { a: undefined, b: undefined, inner: function }。
作用域链: [example环境, 全局环境]。
this 指向全局对象。
执行阶段:
AO 更新为 { a: 1, b: 2, inner: function }。
inner 函数通过作用域链访问 a 和 b。
闭包保留:result 引用 inner,导致 example 的变量对象未被销毁。

通过理解上述过程,可精准定位 this 指向错误、变量意外修改等常见问题,并合理利用闭包实现模块化设计。