2、执行上下文和执行上下文栈
当JavaScript执行到一个函数时候,就会进行准备工作,也就是有个执行上下文。函数写多了,就需要管理函数创建的执行上下文,所以JavaScript创建了执行上下文栈来管理。
可以用一个数组来模拟执行上下文栈的行为
ECStack=[]
接下来可以模拟栗子1代码段的执行上下文栈的行为
例1:
function fun3(){
console.log(‘fun3’)
}
function fun2(){
fun3()
}
function fun1(){
fun()2
}
fun1()
在执行fun1函数之前,JavaScript是先开始解释代码,最先遇到的应该是全局的代码,所以,ECStack执行上下文栈最先压入的是一个全局执行上下文,用globalContext表示。注意的是,globalContext只有在整个应用程序结束的时候才会被pop出去。
接下来是执行函数的阶段,执行函数时,JavaScript或创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕就会将函数执行上下文从栈中pop出来,以下是伪代码:
/*全局*/
ECStack.push( globalContext)
/*fun1()*/
ECStack.push(<fun1> functionContext)
/*fun1中调用了fun2,要创建fun2的执行上下文*/
ECStack.push(<fun2> functionContext)
/*fun2中还调用了fun3,要创建fun3的执行上下文*/
ECStack.push(<fun3> functionContext)
/*fun3执行完毕*/
ECStack.pop()
/*fun2执行完毕*/
ECStack.pop()
/*fun1执行完毕*/
ECStack.pop()
接下来再来看一个栗子2,加深一下理解
例2-1
var scope=‘global scope’
function checkscope(){
var scope=‘local scope’
function f(){
return scope
}
return f()
}
checkscope()
例2-2
Var scope=‘global scope’
function checkscope(){
var scope=‘local scope’
function f(){
return scope
}
return f
}
checkscope()
两段代码其实执行的结果是一样的,但是执行上下文栈的变化是不一样的。
例2-1模拟:
ECStack.push(<checkscope> functionContext)
ECStack.push(<f> functionContext)
ECStack.pop()
ECStack.pop()
例2-1模拟:
ECStack.push(<checkscope> functionContext)
ECStack.pop()
ECStack.push(<f> functionContext)
ECStack.pop()
总结:此篇文章只是大致模拟一下函数在执行前执行上下文的栈堆流程,便于理解。
参考地址:https://github.com/mqyqingfeng/Blog/blob/master/articles