先明确:什么是执行上下文?
可以把它理解成函数运行的专属 "工作空间"。 每次调用函数,JS 引擎都会给这个函数单独开一个 "房间":
- 房间里有:变量对象、作用域链、this
- 函数在这个房间里运行
- 运行结束,房间销毁
一、创建阶段(最核心!调用函数立刻执行)
时机 :函数被调用 → 代码一行一行执行之前 核心任务:三件事,只定义、不赋值
1. 生成变量对象(Variable Object)
变量对象是存放当前上下文所有变量 / 函数的容器,
分三步:
- 收集函数的形参 → 赋值为
undefined - 扫描函数声明 → 直接把函数体赋值进去(函数提升)
- 扫描变量声明 → 只声明,赋值为
undefined(变量提升)
重点:函数声明优先级 > 变量声明
2. 确定作用域链(Scope Chain)
作用域链 = 当前变量对象 + 所有父级执行上下文的变量对象
作用:保证变量、函数的有序访问(先找自己,找不到往上找)
3. 绑定 this
根据调用方式确定 this 指向:
- 普通函数调用 →
window/global - 对象方法调用 → 该对象
- 构造函数 → 实例对象
- 箭头函数 → 继承外层 this
二、执行阶段(代码逐行运行)
时机 :创建阶段完成后 核心任务:
- 把变量对象变成活动对象
- 逐行执行代码:赋值、运算、调用函数
- 执行完毕 → 上下文销毁
三、总结
- 创建阶段 :搭架子 → 变量
undefined、函数就绪、作用域链 + this 确定 - 执行阶段:跑代码 → 变量赋值、函数执行
- 顺序永远是:先创建,后执行