# 前言
在编程这个行业中总是能听到这个词“执行上下文”。那么什么叫“执行上下文”呢?
本篇文章主要是介绍javascript中的执行上下文, 看完之后你可以了解到:
- 执行上下文的类型
- 执行上下文特点
- 执行栈
- 执行上下文的生命周期
# 概念
首先我们来介绍什么是“执行上下文”.
举个例子,生活中,相同的话在不同的场合说可能会有不同的意思,而这个说话的场合就是我们说话的语境。
同样对应在编程中, 对程序语言进行“解读”的时候,也必须在特定的语境中,这个语境就是javascript中的执行上下文。
一句话概括:
执行上下文就是
javascript代码被解析和执行时所在环境的抽象概念。
# 执行上下文的类型
在js中,执行上下文分为以下三种:
- 全局执行上下文:只有一个,也就是浏览器对象(即
window对象),this指向的就是这个全局对象。 - 函数执行上下文:有无数个,只有在函数被调用时才会被创建,每次调用函数都会创建一个新的执行上下文。
- Eval函数执行上下文:
js的eval函数执行其内部的代码会创建属于自己的执行上下文, 很少用而且不建议使用。
# 执行上下文的特点
- 单线程,只在主线程上运行;
- 同步执行,从上向下按顺序执行;
- 全局上下文只有一个,也就是
window对象; - 函数执行上下文没有限制;
- 函数每调用一次就会产生一个新的执行上下文环境。
# JS如何管理多个执行上下文
通过上面介绍,我们知道了js代码在运行时可能会产生无数个执行上下文,那么它是如何管理这些执行上下文的呢?
同时由于js是单线程的,所以不能同时干两件事,必须一个个去执行,那么这么多的执行上下文是按什么顺序执行的呢?
# 执行栈
接下来就对上面的问题做出解答,管理多个执行上下文靠的就是执行栈,也被叫做调用栈。
特点:后进先出(LIFO)的结构。
作用:存储在代码执行期间的所有执行上下文。
(LIFO: last-in, first-out,类似于向乒乓球桶中放球,最先放入的球最后取出)
js在首次执行的时候,会创建一个全局执行上下文并推入栈中。
每当有函数被调用时,引擎都会为该函数创建一个新的函数执行上下文然后推入栈中。
当栈顶的函数执行完毕之后,该函数对应的执行上下文就会从执行栈中pop出,然后上下文控制权移到下一个执行上下文。
比如下面的一个例子🌰:
var a = 1; // 1. 全局上下文环境
function bar (x) {
console.log('bar')
var b = 2;
fn(x + b); // 3. fn上下文环境
}
function fn (c) {
console.log(c);
}
bar(3); // 2. bar上下文环境
@前端进阶之旅: 代码已经复制到剪贴板
如下图:

# 执行上下文的生命周期
执行上下文的生命周期也非常容易理解, 分为三个阶段:
- 创建阶段
- 执行阶段
- 销毁阶段
# 创建阶段
在创建阶段, 主要有是有这么几件事:
- 确定this的值, 也就是绑定this (This Binding);
- **词法环境(LexicalEnvironment)**组件被创建;
- **变量环境(VariableEnvironment)**组件被创建.
一张图方便你理解 🤔

有一些教材中也喜欢用伪代码来实现:
ExecutionContext = {
ThisBinding = <this value>, // 确定this
LexicalEnvironment = { ... }, // 词法环境
VariableEnvironment = { ... }, 