全局执行上下文
在执行全局代码前将window对象确定为全局执行上下文
为全局数据进行预处理
- var 定义的全局变量==undefined,添加为window的属性
- function 声明的全局函数==赋值(fun),添加为window的方法
- this==赋值window对象
函数执行上下文(局部)
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟存在于栈中)
对函数进行预处理
- 形参变量接收实参,添加为函数执行上下文的属性
- arguments 为实参伪数组,添加为函数执行上下文的属性
- var定义的局部变量先复制undefined,添加为函数执行上下文的属性
- function 声明的函数==赋值(fun),添加为函数执行上下文的方法
- this == 赋值为调用函数的对象
开始执行函数体代码
function fn(a1) {
console.log(a1); // 2
console.log(a2); // undefined
a3(); // 'a3()'
console.log(this); // window
console.log(arguments); // 参数伪数组
var a2 = 1;
function a3() {
console.log('a3()');
}
}
fn(2, 3, 4); // window 调用的fn
执行上下文(栈)
- 先生成一个全局执行上下文window,入栈
- 然后执行bar,将bar执行上下文入栈
- 执行foo,将foo执行上下文入栈
- foo执行完毕,出栈
- bar执行完毕,出栈
- 最后剩下window在栈底
面试题目
1.
console.log('gb', i);
var i = 1;
foo(1);
function foo(i) {
if (i === 4) {
return;
}
console.log('fb', i);
foo(i + 1);
console.log('fe', i);
}
console.log('ge', i);
gb undefined
fb 1
fb 2
fb 3
fe 3
fe 2
fe 1
ge 1
// 产生了 5 个执行上下文
理解:这里的foo是递归,结束条件是 i==4
- 首先创建window执行上下文
- 执行函数foo(1),添加foo(1) 入执行栈,输出 fb:1
- 执行函数foo(2),添加foo(2) 入执行栈,输出 fb:2
- 执行函数foo(3),添加foo(3) 入执行栈,输出 fb:3
- 执行函数foo(4),添加foo(4) 入执行栈,满足结束条件 return,foo(4)出栈
foo(3)出栈,输出 fb:3
foo(2)出栈,输出 fb:2
foo(1)出栈,输出 fb:1
==> 产生了 5 个执行上下文
2.
var c = 1;
function c(c) {
console.log(c);
}
c(2); // 报错 c 不是一个 function
// 等效
var c;
function c(c) {
console.log(c);
}
c = 1;
c(2);