什么是执行上下文

JavaScript引擎在执行代码阶段时,通常是调用函数的时候,就会先做一些准备工作,这个准备工作被称为执行上下文,简称EC,或者也可以叫做执行环境

执行上下文也是有不同的,有三个类型:

  1. 全局执行上下文:最基础的执行上下文,一个程序也只会存在一个全局执行上下文,全局上下文会生成一个全局对象,这个对象就是window,并且会将该上下文的中this绑定到该全局对象上。
  2. 函数执行上下文:当函数被调用时都是产生一个新的上下文对象,不管函数是否是重复调用
  3. Eval函数执行上下文:执行在 eval 函数内部的代码也会有它属于自己的执行上下文

而this是由上下文中提供的,我们可以将上下文理解为一个object,这样可以方便认知它。

上下文在创建的时候会创建两个环境:

  1. 词法环境 LexicalEnvironment
  2. 变量环境 VariableEnvironment

词法环境是比较新的一个环境,用于存放let、const等等一些变量和对应的值,其中就有this属性。

变量环境是ES6用于区分var声明而提供的环境,里面存放var声明的变量。

let a = 10;

function foo() {
    let b = 20;
    var d = 40;

    console.log(a, b);
}

foo();

这段代码会生成以下上下文环境(伪代码):

//全局执行上下文
GlobalExecutionContext = {
  //词法环境
  LexicalEnvironment: {
      EnvironmentRecord: {
          type: 'object',
          this: <globalObject>,
          a: <uninitialized>,
          foo: <function>
      },
      outer: <null>
  },
  //变量环境
  VariableEnvironment: {
      EnvironmentRecord: {
          type: 'object',
          this: <globalObject>
      },
      outer: null
  },
}

//函数执行上下文
FunctionExecutionContext = {
  LexicalEnvironment: {
      EnvironmentRecord: {
          type: 'declarative',
          this: <globalObject>, // 严格模式下为undefined
          arguments: {length: 0},
          b: <uninitialized>,
      },
      outer: <GlobalLexicalEnvironment>
  },
  VariableEnvironment: {
      EnvironmentRecord: {
          type: 'declarative',
          this: <globalObject> // 严格模式下为undefined
          d: undefined,
      },
      outer: <GlobalLexicalEnvironment>
  },
}

使用const和let声明的变量在LexicalEnvironment词法环境中,它的值一开始是uninitialized,所以虽然在运行时这个变量就存在于环境中了,但是它是一个未初始化的值,所以在没有执行到对应的声明时,提前读取它会触发ReferenceError报错,这个特性又称之为暂时性死区,而var声明在变量环境中是undefined,所以即时没有被赋值,也是可以正常获取到值,并不会报错。

this会在上下文环境中定义,在下一篇文章,我会讲述定义的规则,这里就不详细说明了。

上下文环境是在运行时创建,在代码使用完就会销毁(除了全局上下文),它就是一个内存中的栈空间,代码在运行时开辟出来,使用完就销毁。虽然这个和作用域很相像,但是不是一个东西,而且是不同生命周期内的产物。

反倒是引擎在创建上下文时,会通过作用域查询对应的变量,然后将需要的内容丢入空间内使用。

其中outer是用于链接作用域的,本人在这块也很模糊,这个作用域个人估计是链的上下文的词法环境和变量环境,因为值只有在运行时才能确定啊。而闭包也是通过outer查找到外部变量。

旧的知识

现在百度到的文章,很大一部分都会讲什么AO、VO啥的,其实这个知识是ES3时代的知识,其实没必要去深入学习,但是还是需要了解一下,免得被弄的眼花缭乱。

分类: 你不知道的JavaScript 标签: 上下文this执行上下文词法环境变量环境作用域链

评论

暂无评论数据

暂无评论数据

目录