代码分类
- 全局代码
- 函数(局部)代码
全局执行上下文(的产生)
- 在执行全局代码前将window确定为全局执行上下文
- 对全局数据进行预处理
– var定义的全局变量赋值为undefined,添加为window的属性
– function声明的全局函数, 添加为window的属性
– this赋值为window - 开始执行全局代码
函数执行上下文(的产生)
- 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
- 对局部数据进行预处理
– 形参变量赋值为实参,添加为执行上下文的属性
– arguments赋值为实参列表,添加到执行上下文属性
– var定义的局部变量赋值为undefined,添加为执行上下文的属性
– function声明的局部函数, 添加为执行上下文的属性
– this赋值为调用函数的对象 - 开始执行函数体的代码
执行上下文栈
- 在全局代码执行前,js引擎就会创建一个栈来存储管理所有的执行上下文对象
- 在全局执行上下文(window)确定后,将其添加到栈中(压栈)
- 在函数执行上下文创建后,将其添加到栈中(压栈)
- 在当前函数执行完后,将栈顶的对象移除(出栈)
- 当所有的代码执行完后,栈中只剩下window
测试题
- 下面的代码依次输出什么内容?
- 整个过程中产生了几个执行上下文?
console.log('gb: ' + i)
var i = 1
foo(1)
function foo(i) {
if (i == 4) {
return
}
console.log('foo() begin:' + i)
foo(i + 1) // 递归调用
console.log('foo() end:' + i)
}
console.log('ge: ' + i)
依次输出的内容是:
gb: undefined
foo() begin: 1
foo() begin: 2
foo() begin: 3
foo() end: 3
foo() end: 2
foo() end: 1
ge: 1
共创建了五个执行上下文,分别是
window全局执行上下文
执行foo(1)时创建的函数上下文
执行foo(2)时创建的函数上下文
执行foo(3)时创建的函数上下文
执行foo(4)时创建的函数上下文