JavaScript的执行上下文是代码执行时的环境,决定了变量、函数、作用域链和this
的访问方式。以下是关键点总结:
1. 执行上下文的类型
- 全局上下文:脚本开始运行时创建,
this
指向全局对象(浏览器中为window
)。 - 函数上下文:每次函数调用时创建,包含局部变量、参数和内部函数。
- Eval上下文:
eval
函数内部的代码(较少使用)。
2. 生命周期
- 创建阶段:
- 确定变量对象(VO,函数中为活动对象AO)、作用域链和
this
。 - 变量提升:处理函数和变量声明(
var
初始化为undefined
,函数声明完整提升)。
- 确定变量对象(VO,函数中为活动对象AO)、作用域链和
- 执行阶段:
- 执行代码,变量赋值、函数调用等操作。
3. 执行上下文栈(调用栈)
- 后进先出(LIFO)结构,管理上下文的创建与销毁。
- 示例:函数调用时入栈,执行完毕出栈,递归可能导致栈溢出。
4. 核心组成
- 变量对象(VO/AO):
- 存储变量、函数声明和形参。
- 函数上下文中称为活动对象(AO),可通过
arguments
访问参数。
- 作用域链:
- 当前VO/AO与父级VO/AO的集合,用于变量查找。
- 函数定义时确定,形成闭包的关键。
this
绑定:- 由调用方式决定(默认、隐式、显式、
new
绑定等)。
- 由调用方式决定(默认、隐式、显式、
5. 变量提升与暂时性死区
var
:声明提升并初始化为undefined
。- 函数声明:整体提升,优先级高于变量。
let/const
:声明提升但未初始化,形成暂时性死区(TDZ),声明前访问报错。
6. ES6后的词法环境
- 词法环境:取代VO,管理
let/const
和块级作用域。 - 变量环境:处理
var
声明,保持提升行为。 - 环境记录:存储标识符绑定,外部引用形成作用域链。
7. 闭包与作用域链
- 内部函数保留外部函数的作用域链,即使外部函数执行完毕。
- 示例:
function outer() { let x = 10; return function inner() { console.log(x); // 闭包引用outer的x }; } const closure = outer(); closure(); // 输出10
8. this
的动态绑定
- 默认绑定:非严格模式指向全局对象,严格模式为
undefined
。 - 隐式绑定:作为方法调用时指向调用对象。
- 显式绑定:
call
/apply
/bind
指定this
。 - 箭头函数:继承外层
this
,无自己的this
。
9. 示例解析
console.log(foo); // 输出函数体
var foo = 'variable';
function foo() {}
console.log(foo); // 输出'variable'
- 创建阶段:函数声明优先于
var
,foo
指向函数。 - 执行阶段:
var foo = 'variable'
覆盖函数引用。
10. 总结
- 执行上下文是JS运行的基础,理解其创建与执行过程、作用域链和
this
机制,是掌握闭包、异步、模块化等高级概念的关键。