ES6的执行上下文

144 阅读3分钟

先来回顾一下ES3的执行上下文

ES3执行上下文包含

1.作用域链

2.环境变量

3.this

下面来介绍ES6的执行上下文的结构

我们将作用域链的功能以及环境变量的功能整合,也就是ES6中的词法环境

词法环境包含环境记录器以及外部环境的引用

环境记录器也就是记录了当前环境的变量和函数申明,如果该上下文为函数上下文,那么环境记录器中需要记录arguments(函数实参),全局上下文没有传参自然不需要记录

全局环境中,环境记录器是对象环境记录器。 在函数环境中,环境记录器是声明式环境记录器。

外部环境的引用相当于作用域链的作用,意味着它可以访问其父级词法环境

词法环境变量的结构如下图所示

image.png

而在ES6中,加入了let 和 const,词法环境只满足var,用let和const定义的变量我们将其放入变量环境中,这就是ES6执行上下文的第二个元素,他与词法变量的结构相同

最后一个依然是this

所以组成执行上下文的三个部分分别是词法环境,变量环境,this

下面看一个直观的例子

代码

let a = 20;
const b = 30;
var c;

function multiply(e, f) {
 var g = 20;
 return e * f * g;
}

c = multiply(20, 30);

上下文

// 首先进入全局上下文
GlobalExectionContext = {
// this
  ThisBinding: <Global Object>,
// 全局上下文的词法变量
  LexicalEnvironment: {
  // 环境记录器
    EnvironmentRecord: {
      Type: "Object",
      // 在这里绑定标识符
      a: < uninitialized >,
      b: < uninitialized >,
      multiply: < func >,
    }
    // 外部环境的引用
    outer: <null>
  },
// 变量环境
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // 在这里绑定标识符
      c: undefined,
    }
    outer: <null>
  }
}
// 这里是函数的上下文
FunctionExectionContext = {
  ThisBinding: <Global Object>,

  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // 在这里绑定标识符
      Arguments: {0: 20, 1: 30, length: 2},
    },
    // 外部环境的引用,指向其父级词法环境
    outer: <GlobalLexicalEnvironment>
  },

VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      // 在这里绑定标识符
      g: undefined
    },
    outer: <GlobalLexicalEnvironment>
  }
}

补充:JS编译与执行

JS执行过程可以分为三步: 语法分析--->预编译阶段--->执行阶段

  • 语法分析:顾名思义进行语法分析,有语法错误会直接抛出并停止执行该代码块
  • 预编译阶段:创建执行上下文的阶段,如上述代码中模拟出的执行上下文的样子
  • 执行阶段:在执行上下文创建好之后,开始逐步执行代码,执行机制也就是事件循环。执行函数时,又会进入到预编译与阶段,创建函数执行上下文,然后再执行

对于JS执行来说,是单线程,我们将其称为IS引擎线程,但是浏览器是多线程,例如事件触发线程,定时器触发线程等,这类线程会将符合条件的事件或函数添加到回调队列中,等待JS引擎线程调用。

参考文章:[译] 理解 JavaScript 中的执行上下文和执行栈 - 掘金 (juejin.cn)

本文的代码及某些定义/概念均引用自此文