执行上下文栈

111 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

可执行代码

JavaScript可执行代码有哪些呢?

三种,全局代码,函数代码,eval代码。

执行上下文

通俗点说,执行上下文就是,当去执行一个函数的时候就会进行准备动作,这个准备动作就叫做“执行上下文”。

JavaScript创建了执行上下文栈来管理执行上下文。

Execution context stack,ECS => 执行上下文栈

让我们举例子了解一下:

假设 执行上下文栈 是一个 数组:

ESC=[]

当JavaScript执行代码时首先遇到全局代码,即globalContext。所以初始化时首先向执行上下文栈压入全局执行上下文。并且,只有当整个应用程序运行结束时,ESC才会被清空,所以在程序结束之前,ESC最底部永远有全局执行上下文。

接下来执行下列代码:

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

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

JavaScript引擎如何执行呢。

当执行一个函数时,就会创建一个函数执行上下文,并且压入执行上下文栈;当函数执行结束时,就会将此执行上下文从栈中弹出。

以上,是执行函数时的流程。(函数执行上下文:functionContext)

即,先在ESC栈中push压入fun1的执行上下文;

再push压入fun2的执行上下文;

再push压入fun3的执行上下文。

因为是栈中,栈中,所以遵循后进先出,即fun3最先执行完毕然后从栈中弹出。

ESC.pop();弹出fun3;

ESC.pop();弹出fun2;

ESC.pop();弹出fun1;

函数全部执行完毕,不要忘记ESC最底层有全局执行上下文glocalContext。

   function foo() {
            console.log('foo1');
    }
        foo();  
   function foo() {
            console.log('foo2');
    }
        foo(); 

这段代码的输出结果是什么?

我们已经了解了执行函数的流程了,那么也照葫芦画瓢吧。

即,在ESC栈种push压入foo()的执行上下文;再压入foo()的执行上下文;

接着去执行foo()函数,发现有两个命名为foo的重复函数。(同级比较当然是取最后一个了,相同命名已经被覆盖了,最后一个才是有效滴)

那就输出结果foo2两个

同时ESC.pop();弹出foo()

ESC.pop();弹出foo();

但是如果:::👇

var foo = function () {
console.log('foo1');
}
foo();  
function foo() {
console.log('foo2');
}
foo();

与上一段代码相比只差了一个var声明,结果截然不同,众所周知函数声明的优先级要比变量声明更高,所以内部代码顺序为:

function foo() {
console.log('foo2');
}
var foo = function () {
console.log('foo1');
}
foo();  
foo();

所以以上结果输出为两次foo1.