关于执行上下文
执行上下文
每当控制器转到可执行代码的时候,就会进入一个执行上下文。执行上下文可以理解为当前代码的执行环境,它会形成一个作用域。
在一个JavaScript程序中,必定会产生多个执行上下文,JavaScript会以栈的方式来处理它们,这个栈成为函数调用栈(call stack)。栈底永远都是全局上下文,栈顶就是当前正在执行的上下文。
执行上下文可以理解为函数执行的环境,每一个函数执行时都会给对应的函数创建一个执行环境。
var color = 'blue';
function changeColor() {
var anotherColor = 'red';
function swapColors() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
}
swapColors();
}
changeColor();
我们用ECStack来标识处理执行上下文的堆栈,第一步,全局上下文入栈。
全局上下文入栈之后,其中可执行的代码开始执行,直到遇到了changeColor(),这一句**函数changeColor创建它自己的执行上下文,因此第二步就是changeColor的执行上下文入栈。
changeColor的上下文入栈之后,控制器开始执行其中的可执行代码,遇到swapColors()之后又**了一个可执行上下文。因此,第三步是swapColors的执行上下文入栈。
在swapColors的可执行代码中,再没有遇到其它能生成执行上下文的情况,因此这段代码顺利执行完毕,swapColors的上下文从栈中弹出。
swapColors的执行上下文弹出后,继续执行changeColor的可执行代码,也没有再遇到其它执行上下文,顺利执行完毕后弹出。这样,ECStack中就只剩下全局上下文了。
全局上下文在浏览器窗口关闭后出栈。(函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。)
在了解了这个过程以后,我们就可以对执行上下文总结一些结论了。
- 单线程
- 同步执行,只有栈顶的上下文处于执行中,其它的上下文需要等待。
- 全局上下文只有唯一的一个,他在浏览器关闭时出栈。
- 函数的执行上下文的个数没有限制。
- 每次某个函数被调用,就会有新的上下文为其创建,即使是调用自身函数,也是如此。
为了巩固一下执行上下文的理解,再来一个简单的例子:
function f1() {
var n = 999;
function f2() {
alert(n)
}
return f2;
}
var result = f1();
result(); // 999
因为f1中的函数f2在f1可执行的代码中 并没有被调用执行,因此,执行f1时,f2不会创建新的上下文,而是直到执行result时候,才创建了一个新的执行上下文。具体演变过程如下: