全局执行上下文
在执行全局代码前将window对象确定为全局执行上下文
为全局数据进行预处理
- var 定义的全局变量==undefined,添加为window的属性
- function 声明的全局函数==赋值(fun),添加为window的方法
- this==赋值window对象
函数执行上下文(局部)
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟存在于栈中)
对函数进行预处理
- 形参变量接收实参,添加为函数执行上下文的属性
- arguments 为实参伪数组,添加为函数执行上下文的属性
- var定义的局部变量先复制undefined,添加为函数执行上下文的属性
- function 声明的函数==赋值(fun),添加为函数执行上下文的方法
- this == 赋值为调用函数的对象
开始执行函数体代码
function fn(a1) {console.log(a1); // 2console.log(a2); // undefineda3(); // 'a3()'console.log(this); // windowconsole.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 undefinedfb 1fb 2fb 3fe 3fe 2fe 1ge 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);
