JavaScript中的执行上下文与作用域链
字数 1304 2025-11-07 12:34:03
JavaScript中的执行上下文与作用域链
描述
执行上下文(Execution Context)是JavaScript代码执行时的环境,包含变量、函数、作用域链等关键信息。作用域链(Scope Chain)是用于解析变量访问权限的机制,由当前执行上下文和所有外层上下文的变量对象组成。理解这两者有助于掌握变量查找、闭包等核心概念。
步骤1:执行上下文的类型
JavaScript中有三种执行上下文:
- 全局执行上下文:代码首次运行时创建,全局唯一,生命周期与程序一致。
- 函数执行上下文:每次调用函数时创建,函数执行完毕后销毁。
- Eval执行上下文(较少使用):在
eval函数内部代码执行时创建。
每个执行上下文包含三个核心组件:
- 变量对象(Variable Object):存储变量、函数声明和形参。
- 作用域链(Scope Chain):由当前变量对象和父级作用域链组成。
- this值:指向当前执行上下文关联的对象。
步骤2:执行上下文的创建过程
以函数执行上下文为例,创建分为两个阶段:
-
创建阶段:
- 创建变量对象:
- 扫描函数参数,添加为属性(值初始为传入值或
undefined)。 - 扫描函数声明,添加为属性(值为函数引用,覆盖同名参数)。
- 扫描变量声明,添加为属性(值初始为
undefined,不覆盖同名函数或参数)。
- 扫描函数参数,添加为属性(值初始为传入值或
- 构建作用域链:复制函数的
[[Scope]]属性(定义时确定),并将当前变量对象添加到链首。 - 确定
this绑定(由调用方式决定)。
- 创建变量对象:
-
执行阶段:
- 逐行执行代码,修改变量对象中的值。
- 遇到变量时,沿作用域链查找。
示例分析
var a = 1;
function foo(b) {
var c = 2;
console.log(a + b + c);
}
foo(3); // 输出6
-
全局上下文创建阶段:
- 变量对象:
a: undefined,foo: <function> - 作用域链:
[全局变量对象] this指向全局对象(如window)。
- 变量对象:
-
全局上下文执行阶段:
- 执行
a = 1,修改变量对象为a: 1。 - 执行
foo(3),创建函数上下文。
- 执行
-
foo函数上下文创建阶段:
- 变量对象:
b: 3,c: undefined(参数b优先,变量c初始化)。 - 作用域链:
[foo变量对象, 全局变量对象](复制foo.[[Scope]]并添加当前变量对象)。 this由调用决定(此处为默认绑定,指向全局对象)。
- 变量对象:
-
foo函数上下文执行阶段:
- 执行
c = 2,修改变量对象为c: 2。 - 执行
console.log(a + b + c):- 查找
a:当前变量对象无a→ 沿作用域链查全局变量对象,找到a=1。 b和c直接在当前变量对象中找到。
- 查找
- 执行
步骤3:作用域链的形成原理
- 函数在定义时就确定了
[[Scope]]属性,包含其外层作用域的变量对象。 - 例如,嵌套函数的作用域链在创建时会包含外层函数的变量对象:
function outer() {
var x = 10;
function inner() {
console.log(x); // 通过作用域链访问outer的x
}
return inner;
}
var innerFunc = outer(); // outer执行后,inner仍能通过作用域链访问x(闭包)
关键点总结
- 执行上下文是动态创建的,而作用域链在函数定义时静态确定。
- 变量查找沿作用域链由内向外,找不到则报
ReferenceError。 - 闭包的本质是函数保留了对定义时作用域链的引用,即使外层函数已执行完毕。