要理解执行上下文栈首先要理解执行上下文,在javascript中有三种类型的可执行代码,它们分别是:全局代码、函数代码、eval代码。当浏览器解析到这些可执行代码时需要进行一些“准备工作”,而这些准备工作就可以理解为执行上下文。而执行上下文栈呢就是将可执行的执行上下文一个个添加进一个栈中,这个栈可以理解为一个类数组的数据结构,当执行一段函数时,就会创建一个执行上下文,并将其加入执行上下文栈中,当函数执行完毕的时候,就会将这个执行上下文弹出。
    为了模拟执行上下文栈的数据结构,我们可以将其当成一个数组ECStack,而全局函数呢就定义为一个globalContext,ECStack始终先添加globalContext,请看一下一段示例:

    1. function fun3() {
    2. }
    3. function fun2() {
    4. fun3()
    5. }
    6. function fun1() {
    7. fun2()
    8. }
    9. function fun() {
    10. fun1()
    11. }
    12. fun()
    13. // 将其用执行上下文栈表示为
    14. // global
    15. ECStack = [
    16. globalContext
    17. ]
    18. // 调用fun
    19. ECStack.push(<fun> functionContext)
    20. // fun中调用了fun1
    21. ECStack.push(<fun1> functionContext)
    22. // fun1中又调用了fun2
    23. ECStack.push(<fun2> functionContext)
    24. // fun2中又调用了fun3
    25. ECStack.push(<fun3> functionContext)
    26. // fun3执行完毕
    27. ECStack.pop()
    28. // fun2执行完毕
    29. ECStack.pop()
    30. // fun1执行完毕
    31. ECStack.pop()
    32. // fun执行完毕
    33. ECStack.pop()
    34. // global执行完毕
    35. ECStack.pop()

    接着静态作用域与动态作用域中的思考中用执行上下文的进行分析

    1. var scope = 'global'
    2. function foo(){
    3. var scope = 'local'
    4. function bar(){
    5. return scope;
    6. }
    7. return bar()
    8. }
    9. foo()
    10. // 执行上下文解析
    11. ECStack.push(<foo> functionContext)
    12. ECStack.push(<bar> functionContext)
    13. ECStack.pop()
    14. ECStack.pop()
    1. var scope = 'global'
    2. function foo(){
    3. var scope = 'local'
    4. function bar(){
    5. return scope;
    6. }
    7. return bar
    8. }
    9. foo()()
    10. // 执行上下文解析
    11. ECStack.push(<foo> functionContext)
    12. ECStack.pop()
    13. ECStack.push(<bar> functionContext)
    14. ECStack.pop()

    说明函数的执行顺序不同。说到javascript的执行顺序,是自上而下的吗,请看一段代码

    1. var foo = function() {
    2. console.info('foo1')
    3. }
    4. foo() // foo1
    5. var foo = function() {
    6. console.info('foo2')
    7. }
    8. foo() // foo2
    1. function foo(){
    2. console.info('foo1')
    3. }
    4. foo() // foo2
    5. function foo() {
    6. console.info('foo2')
    7. }
    8. foo() // foo2

    从上面两端代码可以看出。第一段是变量提升,第二段是函数提升,为何产生不一样的效果呢?

    :::info 本资料内容引用自冴羽大神的博客:传送门 :::