聊一聊JS的执行上下文

JS的代码会按照自上到下的顺序解析执行,
例如:

var foo = function () {

    console.log('foo1');

}

foo();  // foo1

var foo = function () {

    console.log('foo2');

}

foo(); // foo2

如果我们把代码改成这样:

function foo(){

     console.log('foo1');

}

foo() //foo2


function foo(){

    console.log('foo2')

}

foo() //foo2

这个例子全部打印的都是foo2,原因就是在第一个代码示例中,是变量声明提升,也就是说foo提升了; 而在第二个代码示例中,是函数声明提升,也就是说在第二个示例中第二个函数的foo覆盖了第一个foo。

执行上下文

说到执行上下文就要说到JavaScript的可执行代码;
js的可执行代码;可执行代码有三种,分别是:全局代码、函数代码、eval代码。eval现在在规范中已经不再使用,所以不在讨论之中。

比如说:当执行到一个函数的时候,就会进行准备工作,这里的‘准备工作’用更专业的说法来说就是‘执行上下文’。

函数的执行上下文栈

在一个代码中函数会很多,那么如何来管理这么多的执行上下文呢?JavaScript引擎创建了执行上下文栈来管理代码中的执行上下文。

1.首先,栈是一种先进后出的数据结构;我们可以用一个数组来模拟调用栈。

ECStack=[]

2.当遇到全局代码时,执行上下文栈会压入一个全局上下文,我们使用globalContext来表示。

ECStack.push(globalContext)

3.只有当整个程序运行结束,执行上下文栈才会被清空,所以程序结束之前,在ECStack中始终有globalContext。

现在,JS引擎遇到函数代码块了;

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

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

ESCStack在fun1函数调用时会做以下事情

//每一个函数执行时都会创建一个执行上下文并被压入执行上下文栈中
//fun1执行了,创建一个context
//  压栈 
ECStack.push(<fun1 context>) //发现内部还有`fun2`调用
ECStack.push(<fun2 context>) //发现内部还有`fun3`调用
ECStack.push(<fun3 context>) //发现内部还有log函数调用
ECStack.push(<log context>) //里面没了
打印fun3 //代码执行完了,该弹栈了
ECStack.pop(<log context>)
ECStack.pop(<fun3 context>)
ECStack.pop(<fun2 context>)
ECStack.pop(<fun1 context>)

此时ECStack还剩下[globalContext]
// 继续处理其他代码
// globalContext在程序结束前一直会存在

小练习

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



//遇到全局上下文
ECStack.push(globalContext) //此时的调用栈[globalContext]

//调用checkscope,进入checkscope的函数内
ECStack.push(<checkscope context>)  //压栈

//内部没有函数调用,返回函数f
ECStack.pop(<checkscope context>)  //弹栈

//返回的f被调用了
ECStack.push(<f context>)  //压栈
ECStack.pop(<f context>)  //弹栈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值