执行全局代码时会产生一个执行上下文环境,每次调用函数又会产生一个执行上下文环境。当函数调用完成后,这个环境以及里面的数据便会消除,再回到全局执行上下文环境中。处于活动中的执行上下文只有一个。这就好比一个压栈出栈的过程。
下面看一个例子
var a = 10,
fn,
bar = function (x) {
var b = 5
fn(x + b)
}
fn = function (y) {
var c = 5
console.log(y + c)
}
bar(10)
我们只看结果的话很简单,bar执行,调用fn,输出结果就完了
从执行上下文来看呢,
在执行代码前,先创建全局执行上下文环境
变量 | 值 |
---|---|
a | undefined |
fn | undefined |
bar | undefined |
this | windows |
然后代码执行,直到bar(10)执行之前都没有进入函数内部,因此都是在全局执行上下文环境中执行的
变量 | 值 |
---|---|
a | 10 |
fn | undefined |
bar | undefined |
this | windows |
所以只能给a赋值
接下来bar的执行,开始创建bar执行上下文环境
变量 | 值 |
---|---|
x | 10 |
arguments | [10] |
b | undefined |
this | windows |
此时将这个环境压栈,并使其处于激活状态
下面在bar执行上下文环境下执行代码,对环境进一步更新,直到fn被调用
变量 | 值 |
---|---|
x | 10 |
arguments | [10] |
b | 5 |
this | windows |
到了fn了,开始创建fn执行上下文环境
变量 | 值 |
---|---|
y | 15 |
arguments | [15] |
c | undefined |
this | windows |
将fn环境压栈,并激活
在fn的环境下执行代码,更新环境
变量 | 值 |
---|---|
y | 15 |
arguments | [15] |
c | 5 |
this | windows |
好了这样一来,fn的代码就执行完了,需要让fn环境出栈,并销毁里面的变量
再次回到bar的环境执行剩余代码,当bar函数中的内容被全部执行完毕后,也被弹出销毁
又回到全局上下文环境了。全局上下文环境暂时不会被销毁。