Fork me on GitHub

JS-执行上下文和执行栈

执行上下文和执行栈

执行上下文(Execution Context):当前JS代码被解析和执行时所在环境的抽象概念。当前代码的执行环境,会形成一个作用域。
JavaScript中的运行环境包括三种:

  • 全局环境:JavaScript代码运行起来会首先进入该环境;
  • 函数环境:当函数被调用执行时,进入当前函数中执行代码;
  • eval(不建议使用,可忽略)
    JS 程序中,会产生多个执行上下文,JS 引擎会以函数调用栈(call stack)的方式来处理,栈底永远是全局上下文,栈顶是当前正在执行的上下文。
    代码执行过程中,遇到以上三种情况,都会生成一个执行上下文,放入栈中,处于栈顶的上下文执行完毕后,自动出栈,

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var color = 'blue';

function changeColor() {
var anotherColor = 'red';

function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}

swapColors();
}

changeColor();
  1. 全局上下文入栈;
    全局上下文入栈

  2. 执行到changeColor(),创建当前函数的执行上下文;
    函数执行栈

  3. 执行changeColor中的可执行代码,遇到swapColors(),创建swapColors执行上下文;
    函数执行栈

  4. swapColors函数执行完成后,swapColors EC出栈;
    函数执行栈
  5. 继续执行changeColor函数,执行完成后,changeColor EC出栈,只剩下全局执行上下文。
    全局上下文入栈
  6. 全局上下文在浏览器窗口关闭后出栈。

注意:函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。
全局上下文入栈

生命周期:创建阶段、执行阶段、回收阶段
全局上下文入栈

  1. 创建阶段(函数创建,但未执行)

    • 创建变量对象:首先初始化函数的参数 arguments,提升函数声明和变量声明
    • 创建作用域链
    • 确定 this 指向
  2. 函数内部执行时,会形成新的私有作用域,然后依次执行

    • 如果有形参,先给形参赋值
    • 进行私有作用域的预解释,函数声明优先级比变量声明高,但可以重新赋值,
    • 私有作用域中的代码从上到下执行
      每次调用函数创建一个新的执行上下文,JS 引擎创建了执行栈来管理执行上下文,执行栈是一个存储函数调用的栈结构,遵循先进后出的原则。

多个函数执行过程:

  • JS 执行在单线程上,所有的代码都是排队执行
  • 首先创建全局执行上下文,压入执行栈的底部
  • 函数执行时就创建新的执行上下文,压入执行栈的底部。
  • 函数执行完,该函数执行上下文出栈,等待垃圾回收
  • 浏览器的 JS 执行引擎总是访问栈顶执行上下文
  • 全局执行上下文只有唯一一个,它在浏览器关闭时出栈。
-------------本文结束感谢阅读-------------