执行上下文一般有三种,全局执行上下文、函数执行上下文、eval 执行上下文
1. 全局执行上下文
全局执行上下文只有一个,在客户端里是浏览器自己创建的,就是我们经常能遇见的 window 对象
全局执行上下文会有大量的方法,属性,也是我们全局变量和函数定义的载体。
在执行全局代码之前,
全局执行上下文会对代码进行预处理:
* var 定义的变量赋值为 undefined,并且被 window 收录为属性
* 全局声明的 function 函数,被 window 收录为方法
做完这些以后开始执行全局代码
2. 函数执行上下文
函数执行上下文会出现比较多,具体什么时候出现呢?
函数执行上下文在准备调用函数,执行函数体的内容之前被创建
这时函数执行上下文也会对局部数据处理
* 形参变量被赋值,被函数执行上下文收录为属性
* arguments 赋值实参列表,被函数上下文收录为属性
* var 声明的变量,被赋值 undefined,被函数上下文收录为属性
* function 声明的函数赋值,被收录为方法
* this 赋值为调用函数的对象
做完以上内容,就开始执行函数内局部代码
但是这么多的执行上下文,放在哪里呢?一般语言都讲究容器,像栈内存,堆内存都是为了存放数据而生,所以执行上下文都存放在执行栈里
执行上下文栈(调用栈)
它是用来存储代码执行之前创建的各种栈,有先进后出的特性
在代码首次运行的时候,浏览器会创建一个全局执行上下文栈,放到调用栈中(即压栈),然后当每次遇见调用函数的时候,创建的函数执行上下文栈依次压栈,执行完一个函数就会出栈一个上下文,直到最后还是有个全局上下文栈在最低部
我们来看看下面代码的打印顺序
function fun1() {
fun2();
console.log('fun1');
};
function fun2() {
fun3();
console.log('fun2');
};
function fun3() {
console.log('fun3');
};
fun1(); // fun3 fun2 fun1
结果中我们能看到:fun3、fun2、fun1
这就是我们所说的,遇到函数调用就创建函数上下文压栈,并且栈中内容先进后出,fun1、fun2、fun3 顺次压栈,出栈顺序就会反过来。
总结
- 全局执行上下文只有一个,代码执行前由浏览器创建
- 函数执行上下文在函数调用的时候创建
- 所有的执行上下文存放在调用栈里,符合先进后出原则
- var 声明的变量被赋值 undefined,并且收录变为所在上下文的属性,let、const就没有收录,所以 var 创建的变量会提升
- this 是被调用函数的对象确定的,没有调用函数的对象,它就指向 window
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。