关于执行上下文

执行上下文
每当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。
在一个JavaScript程序中,必定会产生多个执行上下文,JavaScript会以栈的方式来处理它们,这个栈成为函数调用栈(call stack)。栈底永远都是全局上下文,栈顶就是当前正在执行的上下文。
执行上下文可以理解为函数执行的环境,每一个函数执行时都会给对应的函数创建一个执行环境。

    var color = 'blue';

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

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

我们用ECStack来标识处理执行上下文的堆栈,第一步,全局上下文入栈。
关于执行上下文
全局上下文入栈之后,其中可执行的代码开始执行,直到遇到了changeColor(),这一句**函数changeColor创建它自己的执行上下文,因此第二步就是changeColor的执行上下文入栈。
关于执行上下文

changeColor的上下文入栈之后,控制器开始执行其中的可执行代码,遇到swapColors()之后又**了一个可执行上下文。因此,第三步是swapColors的执行上下文入栈。

关于执行上下文

在swapColors的可执行代码中,再没有遇到其它能生成执行上下文的情况,因此这段代码顺利执行完毕,swapColors的上下文从栈中弹出。
关于执行上下文

swapColors的执行上下文弹出后,继续执行changeColor的可执行代码,也没有再遇到其它执行上下文,顺利执行完毕后弹出。这样,ECStack中就只剩下全局上下文了。
关于执行上下文

全局上下文在浏览器窗口关闭后出栈。(函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。)
关于执行上下文

在了解了这个过程以后,我们就可以对执行上下文总结一些结论了。

  • 单线程
  • 同步执行,只有栈顶的上下文处于执行中,其它的上下文需要等待。
  • 全局上下文只有唯一的一个,他在浏览器关闭时出栈。
  • 函数的执行上下文的个数没有限制。
  • 每次某个函数被调用,就会有新的上下文为其创建,即使是调用自身函数,也是如此。

为了巩固一下执行上下文的理解,再来一个简单的例子:

    function f1() {
      var n = 999;
      function f2() {
        alert(n)
      }
      return f2;
    }
    var result = f1();
    result(); // 999

因为f1中的函数f2在f1可执行的代码中 并没有被调用执行,因此,执行f1时,f2不会创建新的上下文,而是直到执行result时候,才创建了一个新的执行上下文。具体演变过程如下:
关于执行上下文