执行上下文

发布时间 2023-12-30 23:57:12作者: 前端自信逐梦者

1. 什么是执行上下文?

执行上下文就是js代码被解析和执行所在的环境,是一种抽象概念。

2. 执行上下文的类型

2.1.全局执行上下文

不在任何函数中的代码都在全局执行上下文中,它做了两件事:

  1. 创建一个全局对象,在浏览器中全局对象就是window对象
  2. 将this指向这个全局对象
2.2.函数执行上下文

每次函数调用是,都会为这个函数创建一个新的执行上下文,每个函数都拥有自己的执行上下文,但是
只有在函数被调用的时候才会创建。函数的执行上下文数量可以是任意个

2.3.eval函数执行上下文

运行在eval函数中的代码也有自己的执行上下文。(了解即可,不常用)

3. 执行上下文栈

js引擎用创建一个执行上下文栈去管理执行上下文。(先进后出)

let a = 'Hello World!';
function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}
function second() {
  console.log('Inside second function');
}
first();

分析代码:

首先遇到全局代码,创建一个全局上下文环境,压入到执行上下文栈中,又遇到了函数,会创建一个函数执行上下文环境,压入到执行上下文栈的栈顶,js引擎会执行执行上下文栈顶的函数,当函数执行完毕之后,改函数的函数执行上下文环境会从执行上下文栈中弹出,继续执行下一个执行上下文中的代码。
注意:全局上下文只有唯一的一个,它在浏览器关闭时出栈。
注意:函数中,遇到return能直接终止可执行代码的执行,因此会直接将当前上下文弹出栈。

4. 执行上下文的声明周期

4.1.创建阶段

在创建阶段,会做三件事:

es3
  • 创建变量对象:首先初始化函数的参数arguments(全局执行上下文的创建没有创建 arguments 这一步),提升函数声明和变量声明
  • 创建作用域链:在执行期的上下文的创建阶段,作用域链是在创建变量对象之后创建的。作用域链本身就包含变量对象,作用域链用于解析变量,当被要求解析变量的时候,js从代码嵌套的最内层开始,如果最内层没有找到该变量,就会跳转到上一层的父作用域内查找,直到找到该变量。这种js引擎一路向上遍历执行上下文直至解析处在函数内部触发的变量和函数的概念就叫作用域链
  • 确定this指向:js中this关键字指的是执行上下文所属的作用域。一旦作用域链被创建,JS引擎就会初始化this关键字的值。

注意:es5以上,对于执行上下文的创建阶段有所调整,移除了es3中的变量对象AO和活动对象VO,引入了词法环境组件和变量环境组件来代替

es5
  • 确定this指向: 在全局执行上下文中,this指向的全局对象。在函数执行上下文中,this指向取决于函数如何调用。
  • 创建词法环境组件:词法环境就是一个用于定义特定变量和函数标识符的一种数据结构。词法环境内部有两个组件:1.环境记录项:用来储存变量和函数声明的实际位置。2.外部环境的引用:可以访问父级作用域。作用和es3中的作用域链相似。
  • 创建变量环境组件:变量环境也是一个词法环境,因此它具有上面定义的词法环境的所有属性。在 ES6 中,词法环境和 变量环境的区别在于前者用于存储函数声明和变量(let和const关键字)绑定,而后者仅用于存储变量(var)绑定,因此变量环境实现函数级作用域,通过词法环境在函数作用域的基础上实现块级作用域。箭头函数没有自己的上下文,没有arguments(可以用...rest代替),也不存在变量提升。
4.2.执行阶段

在这一阶段,代码执行才真正开始。
在创建阶段之后,变量对象中的变量值为undefined,如果在此时执行代码,会报错。
在执行阶段,js引擎会再次读取执行上下文,用变量的实际值更新变量对象,编译器再将代码编译成计算机可执行的字节码后执行。

4.3.回收阶段

回收阶段是指当一个函数执行完毕或者当前执行上下文被弹出栈时,上下文被回收的过程。

  • 垃圾回收:js引擎会检查当前的执行上下文中的变量或者函数有没有被其他引用,如果没有,则将其标记为垃圾对象,被垃圾回收器回收。
  • 变量销毁:js引擎会销毁当前执行上下文中所有的变量。当函数执行完毕后,会销毁函数执行上下文中的所有局部变量。在全局执行上下文忠,全局变量只有在浏览器关闭的时候才会销毁。
  • 闭包变量销毁: 如果当前执行上下文是一个闭包函数的执行上下文,那么其中的闭包变量就不会被销毁,除非外层函数的引用被销毁时,闭包中的变量才会被销毁。
  • 执行上下文弹出:js引擎会将当前的执行上下文从执行上下文栈中弹出。