JavaScript 之执行上下文

tips:
若是发现文中有描述不许确的地方,请必定要在评论区留言告知,十分感谢!
若是本篇文章对你有所帮助,还请帮忙点个赞,你的点赞对我来讲是莫大的鼓励!
github blog: https://github.com/jeuino/Blo...

前言

在上篇文章《JavaScript 之词法分析和语法分析》中,咱们介绍了词法分析和语法分析的基本概念。本篇文章将继续讲解什么是执行上下文。前端

Snipaste_2020-03-10_23-21-35

可能有的读者会疑惑,预编译阶段和执行代码阶段与执行上下文是什么关系?这个问题会在讲解执行上下文的生命周期时作出解释。敬请期待《JavaScript 之执行上下文的生命周期》

执行上下文

执行上下文(Execution Context),也称为执行环境,就是当前 JavaScript 代码执行时所在环境的抽象概念,能够理解为当前代码的运行环境。git

在 JavaScript 中,执行环境主要分为:github

  • 全局执行环境: 全局执行环境是最顶层的一个执行环境,是 JavaScript 代码最开始运行时的默认环境。
  • 函数执行环境:函数执行环境是调用函数时建立的,每次调用函数,都会为该函数建立一个新的执行上下文。
  • eval 函数执行环境: eval 函数在执行其内部代码时,也会建立属于本身的执行上下文。(由于 eval 函数并不建议使用,因此这里不作介绍。)

在一个 JavaScript 程序中,一般状况下都会存在多个执行上下文,由于一个 JavaScript 文件中可能声明了多个函数。当多个函数被调用时,就会建立多个执行上下文,那么这些执行上下文是如何管理的呢?segmentfault

JavaScript 引擎建立了执行上下文栈(Execution Context Stack)(也被称为函数调用栈) 来管理执行上下文。数组

执行上下文栈

首先咱们来了解下什么是栈数据结构浏览器

栈中数据的存取方式相似给枪上子弹,先上的子弹最后打出,后上的子弹先打出。
特色:先进后出,后进先出数据结构

理解了栈数据结构,咱们继续来讲执行上下文栈是如何管理执行上下文的?函数

咱们用数组来模拟执行上下文栈的行为:ECStack = [];ui

function fn2() {
  console.log('fn2')
}

function fn1() {
  console.log('fn1')
  fn2();
}

fn1();

分析上述这段代码在执行过程当中,执行上下文栈的行为是什么样的:this

  1. 在代码开始执行时,首先会建立全局执行上下文并将其压入到执行上下文栈中
ECStack.push(global_EC);
  1. 全局上下文入栈后,其中的可执行代码开始执行,直到遇到函数 fn1;fn1 开始执行时,会建立 fn1 函数执行上下文并将其压入到执行上下文栈中
ECStack.push(fn1_EC);
  1. 以此类推,当开始执行 fn2 时,会建立 fn2 函数执行上下文并入栈;此时全部的执行上下文都已经入栈;
ECStack.push(fn2_EC);

Image12

  1. 当 fn2 执行完毕,fn2 函数执行上下文出栈;
ECStack.pop();
  1. 当 fn1 执行完毕,fn1 函数执行上下文出栈;
ECStack.pop();
  1. 当全部代码执行完毕,就又回到了全局执行上下文;当程序退出时,即关闭浏览器或网页时,全局执行上下文才出栈。
ECStack.pop();

Image13

总结:

  • JavaScript 是单线程同步执行的,只有栈顶的上下文处于执行中,其余上下文须要等待;
  • 全局执行上下文永远第一个入栈,也就是说它永远在栈底;而当前执行的函数执行上下文永远最后一个入栈,也就是说它永远在栈顶。
  • 执行上下文出栈后,保存在该环境中的全部变量和函数定义也随之销毁。

下一篇

在每一个执行上下文中,都包括三个重要的属性:

  • 变量对象(Variable Object,VO)
  • 做用域链(Scope Chain)
  • this指向

Image14

下篇文章将继续介绍执行上下文中的变量对象,敬请期待。

参考文章:
JavaScript深刻之执行上下文
前端基础进阶(二):执行上下文详细图解
JS 执行环境、做用域链、活动对象
相关文章
相关标签/搜索