JS中的执行上下文与环境

71 阅读4分钟

JS中的执行上下文与环境

2023 / 5 / 30 By:Awayer

1.什么是执行上下文

通俗点说就是一段JS代码在执行时,它实际上就是运行在执行上下文中,在JS中一共有3种执行上下文:

全局执行上下文

之所以叫全局,那说到就是不在函数中的代码,他是为了运行代码主体而创建的执行上下文。它会执行两件事:创建一个全局的 window对象(浏览器的情况下),并且设置 this 的值等于这个全局对象。一个程序中只会有一个全局执行上下文。

函数执行上下文

每当一个函数被调用时,都会为该函数创建一个新的执行上下文,每个函数都有它自己的执行上下文,不过是在函数被调用时创建的。

Eval函数执行上下文

eval函数有属于他自己的执行上下文,由于eval函数不经常使用,所以这里不做讨论,如有兴趣可以看这篇文章:JavaScript 中 Eval 函数的前世今生,执行代码字符串 - 掘金 (juejin.cn)

执行上下文的生命周期包括三个阶段:创建阶段→执行阶段→回收阶段

2.执行上下文的创建

创建一共分为3个阶段:

(1)绑定this

(2)创建词法环境组件

(3)创建变量环境组件

(1) 确定this

在全局执行上下文中,this指向全局对象,浏览器中指向window。

在函数执行上下文中,this的指向取决于调用者,下一篇文章我将详细讲解this指向问题

(2) 词法环境

  • 官方的定义:词法环境是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符和具体变量和函数的关联。一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成。

环境记录器:用来储存变量和函数声明的实际位置

外部环境引用:用来访问父级的词法环境

  • 通俗点说: 词法环境可以拥有标识符和变量的映射。词法环境就是在JavaScript 引擎创建一个执行上下文时,创建的用来存储变量和函数声明的环境,它可以使代码在执行期间,访问到存储在其内部的变量和函数,而在代码执行完毕之后,从内存中释放掉。

词法环境分为两种:

  • 在全局执行上下文中,它时一个没有外部环境引用的词法环境,因为全局环境的外部引用时null。
  • 在函数环境中,函数内部定义的变量会被存储在环境记录器中,并且引用的外部环境可能是全局环境,或者任何包含此内部函数的外部函数。

(3) 变量环境

变量环境与词法环境十分相似。在 ES6 中,词法环境和变量环境的明显不同就是前者被用来存储函数声明和变量(let/const)的绑定,而后者只用来存储 var 变量的绑定。

3.执行上下文栈

执行上下文的过程类似与栈(先进后出),当 JavaScript 引擎第一次遇到我们写的脚本时,它会创建一个全局的执行上下文并且压入当前调用栈。每当引擎遇到一个函数调用,它会为该函数创建一个新的函数执行上下文并压入栈的顶部。

拿下面的代码举个例子:

var say = function(){
    hello();
}

var hello = function(){
    console.log("Hello,world!");
}

say();

当上述代码运行时,一共发生了如下步骤:

  1. 当上述代码在浏览器加载时,JavaScript 引擎创建了一个全局执行上下文并把它压入当前执行栈。
  2. 调用了 say函数,创建 say函数的执行上下文,并压入执行栈中。
  3. 进入 say函数 内部,调用了 hello函数,创建 hello函数的执行上下文,并压入执行栈中。
  4. hello函数执行完了,将 hello 移出执行栈
  5. say函数执行完了,将 say 移出执行栈

如下图:

808c5d22-a29c-4b14-b8e7-8dcf138c7dad.png

本篇到此,完。