1

执行上下文一般有三种,全局执行上下文、函数执行上下文、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

码路芽子
81 声望12 粉丝

简单的随心的