Please enable Javascript to view the contents

从头学习js-3-执行上下文栈

 ·  ☕ 2 分钟

这个系列是我读冴羽老师博客的感悟,
加入了个人的解读和练习题的解答

我们知道在js中有变量提升,
所以js引擎在解析代码的时候不是一行一行去执行的,而是一段一段去分析
(暂且以函数花括号来划分段)

实际环境中的函数可能是一层套一层执行的,加上函数有各自的静态作用域
javascript引擎创建了执行上下文栈(Execution context stack,ECS)来管理这些情况

由于函数的执行是有顺序的,执行上下文栈是先进后出的栈结构

我们这里用数组来模拟它

1
ECStack = []

首先执行全局代码,此时在ECStack中压入一个 globalContext

1
2
3
ECStack = [
  globalContext
]

然后我们执行下面的实例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function a() {
  console.log("run a")
  b()
}

function b() {
  console.log("run b")
}

a()

首先执行a函数,在ECStack中压入函数a的执行上下文,

1
2
3
4
ECStack = [
  <a> functionContext,
  globalContext
]

发现执行函数a中,需要执行b函数(此时a还没执行完,没有出栈),在ECStack中压入函数b的执行上下文

1
2
3
4
5
ECStack = [
  <b> functionContext,
  <a> functionContext,
  globalContext
]

函数b执行完后,函数b的执行上下文出栈,ECStack.pop()
然后函数a也执行完了,继续 ECStack.pop()

就是这么一个执行栈


另一个例子:
代码A

1
2
3
4
5
6
7
8
9
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();

代码B

1
2
3
4
5
6
7
8
9
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();

首先代码A和代码B 都会打印 localscope,具体原因在上一篇作用域中有解释
但不同的是A和B的执行上下文的顺序不同
伪代码是这样的

1
2
3
4
5
//代码A
ECStack.push(<checkscope> functionContext)
ECStack.push(<f> functionContext)
ECStack.pop() //f 执行结束
ECStack.pop() //checkscope 执行结束
1
2
3
4
5
//代码B
ECStack.push(<checkscope> functionContext)
ECStack.pop() //checkcope 执行结束
ECStack.push(<f> functionContext)
ECStack.pop() //f 执行结束
分享

Llane00
作者
Llane00
Web Developer