zoukankan      html  css  js  c++  java
  • 深入js——执行上下文栈

    前言

    js的很多不太好理解的概念,比如作用域、this、闭包,可以说都与执行上下文有关,弄懂了执行上下文,再去理解这些概念就没有难度了。

    可执行代码

    但js每执行一段可执行代码,就会进入一个执行上下文;js的可执行代码有3种:

    • 全局代码
    • 函数代码
    • eval代码
      因此,js对应有3种执行上下文:全局上下文、函数上下文、eval上下文。

    执行上下文栈

    当js执行一段代码时,可能出现很多执行上下文,那如何管理这些上下文呢?答案是通过栈来管理,把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈
    每进入一个执行上下文,js就会向栈中push当前上下文,每退出一个执行上下文就会pop当前此上下文。因此堆栈底部永远都是全局上下文(global context),而顶部就是当前(活动的)执行上下文。

    通过浏览器控制台查看调用栈

    • 查看Call Stack
      打开控制台,在“Source”标签下打断点,可以在右边的Call Stack中查看到调用栈的当前状态以及变化。
      调用栈
      从上图可以看出,当执行到foo函数时,调用栈中从上到下有3个执行上下问,分别为当前上下文foo,bar上下文和全局上下文(anonymous译匿名者)。

    可以通过在不同执行上下文打断点,观察Call Stack变化,可以更好的理解执行上下文栈。

    • 打印调用栈
      console.trace可以打印出调用栈的信息。
      在foo函数内部执行console.trace(),可以打印出调用栈的当前状态。
      console.trace()

    思考题

    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f();
    }
    checkscope();
    
    var scope = "global scope";
    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f;
    }
    checkscope()();
    

    以上2段代码的执行结果一样,但它们的调用栈变化却不一样。可以先自己分析下,然后再通过Call Stack检验下看对不对。下面做简要分析:
    第一段代码,调用栈的变化过程:

    Stack.push(<anonymous>)
    Stack.push(<checkscope>);
    Stack.push(<f>);
    Stack.pop(); // <f>
    Stack.pop(); // <checkscope>
    Stack.pop(); // <anonymous>
    

    第二段代码,调用栈的变化过程:

    Stack.push(<anonymous>)
    Stack.push(<checkscope>);
    Stack.pop(); // <checkscope>
    Stack.push(<f>);
    Stack.pop(); // <f>
    Stack.pop(); // <anonymous>
    

    小结

    通过Call Stack可以很清楚看出调用栈的变化,多试多观察栈的变化,对调用栈就会很清楚啦。
    本文可以算是从宏观上讲了执行上下栈的变化,那执行上下文里面是怎样的呢?又是怎样变化的呢?
    接下来讲讲与执行上下文相关的变量对象、作用域链和this。

    参考:
    冴羽深入js系列
    汤姆大叔深入js系列
    极客时间——浏览器工作原理与实践课程

  • 相关阅读:
    cf1100 F. Ivan and Burgers
    cf 1033 D. Divisors
    LeetCode 17. 电话号码的字母组合
    LeetCode 491. 递增的子序列
    LeetCode 459.重复的子字符串
    LeetCode 504. 七进制数
    LeetCode 3.无重复字符的最长子串
    LeetCode 16.06. 最小差
    LeetCode 77. 组合
    LeetCode 611. 有效三角形个数
  • 原文地址:https://www.cnblogs.com/youhong/p/12204739.html
Copyright © 2011-2022 走看看