js系列(更新中)-js执行上下文

1、执行上下文的概念

为了表示不同的运行环境,JavaScript中有一个执行上下文(Execution context,EC)的概念。代码运行是在一定的环境之中运行的,这个运行环境我们就成为执行环境,也就是执行上下文。

 javascript运行的代码环境有三种:

                全局代码:代码默认运行的环境,最先会进入到全局环境中

                函数代码:在函数的局部环境中运行的代码

                Eval代码:在Eval()函数中运行的代码

        全局上下文是最外围的一个执行环境,web浏览器中被认为是window对象。在初始化代码时会先进入全局上下文中,每当一个函数被调用时就会为该函数创建一个执行上下文,每个函数都有自己的执行上下文。为了便于理解看下图

js系列(更新中)-js执行上下文

上图中,一共用4个执行上下文。紫色的代表全局的上下文;绿色代表person函数内的上下文;蓝色以及橙色代表person函数内的另外两个函数的上下文。

注意:不管什么情况下,只存在一个全局的上下文,该上下文能被任何其它的上下文所访问到。也就是说,我们可以在person的上下文中访问到全局上下文中的sayHello变量,当然在函数firstName或者lastName中同样可以访问到该变量。至于函数上下文的个数是没有任何限制的,每到调用执行一个函数时,引擎就会自动新建出一个函数上下文,换句话说,就是新建一个局部作用域,可以在该局部作用域中声明私有变量等,在外部的上下文中是无法直接访问到该局部作用域内的元素的。

2、执行环境的生命周期

执行上下文的生命周期:创建 -> 执行 -> 回收

2.1. 创建阶段

  • 创建作用域链(变量对象+父级执行环境的变量对象)
  • 创建变量对象(包括局部变量、函数以及函数参数)
  • 确定 this 的指向

由此,一个执行环境可以由包含作用域链、变量对象和 this 指针的对象组成:

executionContextObj = {
  scopeChain: {},
  variableObject: {},
  this: {}
}

2.2. 代码执行阶段

  • 指定变量的值和函数的引用
  • 解释并执行代码

2.3. 回收阶段

执行上下文出栈被垃圾回收机制进行回收。

3、JavaScript执行上下文过程(执行栈)

JavaScript中,用的方式来管理执行上下文,我们可以称它为执行栈,也可以叫做函数调用栈(Call Stack)。栈是遵循“先进后出,后进先出”的顺序来进行存储。

我们可以把理解成为一个只有一个开口的容器,先放进去的东西处于容器的最底部,而且如果要拿出来的话,它也是最后一个被拿出来(先进后出)。

在栈中,处于最底部的就是我们最开始创建的全局执行上下文对象,它永远是处于栈底。而处于栈顶就是当前正在执行的上下文。也就是当前执行的函数执行上下文会被放在栈顶。

栈的执行流程分为入栈、执行、出栈三个部分。

  • 入栈:代码执行的时候,上下文被创建,并被压入栈中
  • 执行:被压入的上下文中处于栈顶的就是当前的执行上下文,当这个函数被调用完成之后,上下文对象被销毁
  • 出栈:当上下文被销毁后会从栈顶被弹出,称为出栈,紧接着下一个上下文开始执行。

下面我们通过一个栗子来加深理解:

function text(){
    console.log('text')
    function text1(){
      console.log('text1')
    }
  text1()
}
text()
复制代码

执行流程:

  1. 创建全局上下文环境,全局执行上下文入栈,处于栈底
  2. 遇到text(),创建函数text的上下文对象,text的执行上下文入栈
  3. 在函数text内部执行可执行代码,遇到text1(),创建text1的上下文对象,text1的执行上下文入栈
  4. text1()代码执行完之后没有新的函数了,那么text1()执行完毕,弹出
  5. text1()弹出后接着执行text()的代码,同样没有遇到新的函数,那么text()执行完毕,弹出
  6. 此时,页面栈中就只剩下全局上下文在栈底,如果这个时候页面关闭了,那么全局上下文也弹出栈

js系列(更新中)-js执行上下文

4、总结:

  • 单线程
  • 同步执行
  • 唯一的一个全局上下文
  • 函数的执行上下文的个数没有限制
  • 每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此。
  • JavaScript执行上下文的过程中,对于所有的上下文对象,只有栈顶的上下文是正在被执行的,其他上下文是处于等待的状态,这也是因为JavaScript是单线程所致
  • 全局上下文在整个调用栈永远都是处于栈底,而且只有唯一的一个,当页面处于活动状态的时候,全局上下文是一直存在的,直到关闭页面它才销毁。

 

上一篇:2021-02-05


下一篇:最长公共子序列