执行上下文和作用域

151 阅读3分钟

执行上下文

  • 全局执行上下文ECG 函数执行上下文EC 块执行上下文(es6 let和const拥有) eval函数执行上下文
  • 执行上下文由执行上下文栈ECS管理

js引擎执行js脚本有两个阶段 解析阶段和执行阶段

解析阶段

  1. 生成执行上下文ECG/EC 全局执行上下文整个程序有且只有一个,函数执行上下文呢可以有无数个, 生成之后会被压入到ECS中
  2. 执行上下文会创建词法环境组件,变量环境组件,并完成this的绑定
    • 词法环境:
      • 是一种标识符-变量映射的数据结构 标识符就是变量/函数名,变量标识符实际的引用地址,词法环境由环境记录器和一个可能为null的外部环境引用构成,全局词法环境中的环境记录器被称为对象环境记录器,用来存储标准内置对象和自定义全局的对象和全局函数,全局环境的外部环境引用值是null,函数词法环境中的环境记录器被称为声明式环境记录器,存储着函数内的所有变量和函数声明,形参还有arguments ,外部环境的引用就是上一层的词法环境或者全局环境
      • 词法环境可以理解为作用域 就是当前执行上下文中定义的变量(标识符)可以访问的范围
    • 变量环境:
      • 变量环境也是一种词法环境 它的环境记录器就是var声明的变量 用以区别let和const
  3. 词法环境创建之后会对当前词法作用域下的变量和函数声明进行提升和预编译,
  4. 再根据this的四种绑定规则进行this的绑定

执行阶段

  • 会对当前词法作用域下的变量进行赋值操作 并执行代码

变量对象

  • 每一个执行上下文都有一个与之相关的变量对象VO 全局环境就是全局对象GO 函数环境就是活跃对象AO
  • 变量对象里最初只保存着arguments用来初始化函数(GO不存在),当前执行上下文中的代码被执行的时候会创建一个scope chain作用域链,作用域链的顶部始终是自己的AO,下一个就是包含上下文,底部始终是GO,查找标标识符会从作用域链的顶部依次向下查找一直到GO,GO还不存在就报错

整体执行流程

  1. 在执行js代码的前一刻生成全局执行上下文ECG,压入执行上下文栈ECS中,创建全局词法环境组件,变量环境组件,绑定this,然后执行代码。
  2. 遇到函数调用就生成一个函数执行上下文并压入到ESC的栈顶,创建函数的词法环境组件,变量环境组件,完成this绑定,然后执行函数的代码
  3. 执行完之后就将当前的EC从ECS栈顶弹出,然后继续执行ECS栈顶的下一个执行上下文中的函数,全部代码执行完毕之后就将ECG从执行上下文栈弹出,等待虚拟机垃圾回收