DeanTG / interview

0 stars 0 forks source link

Execution Context #4

Open DeanTG opened 1 year ago

DeanTG commented 1 year ago

link

DeanTG commented 1 year ago

简而言之,执行上下文是对 JavaScript 代码执行环境的一种抽象,每当 JavaScript 运行时,它都是在执行上下文中运行。 (给执行上下文环境下一个通俗的定义——在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。)

DeanTG commented 1 year ago

执行上下文类型:

DeanTG commented 1 year ago

执行栈

执行栈,在其它编程语言中被叫做“调用栈”,是一种 LIFO(后进先出)栈的数据结构,被用来存储代码运行时创建的所有执行上下文。

当 JS 引擎开始执行第一行 JavaScript 代码时,它会创建一个全局执行上下文然后将它压到执行栈中,每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。

引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。

DeanTG commented 1 year ago

执行上下文的创建分为三个阶段:

  1. 创建阶段;
  2. 执行阶段:执行变量赋值、代码执行
  3. 回收阶段:执行上下文出栈等待虚拟机回收执行上下文
DeanTG commented 1 year ago

执行上下文的创建阶段

DeanTG commented 1 year ago

词法环境

词法环境是一个包含标识符变量映射的结构

  • 环境记录:存储声明的变量和函数( let, const, function,函数参数)
  • 外部环境引用:作用域链
DeanTG commented 1 year ago

变量环境

同样是一个词法环境,其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。

变量环境组件(VariableEnvironment) 是用来登记var function变量声明,词法环境组件(LexicalEnvironment)是用来登记let const class等变量声明。

变量对象的创建过程: img

  1. 创建arguments对象,检查当前上下文中的参数,建立该对象的属性与属性值,仅在函数环境(非箭头函数)中进行,全局环境没有此过程

  2. 检查当前上下文的函数声明,按代码顺序查找,将找到的函数提前声明,如果当前上下文的变量对象没有该函数名属性,则在该变量对象以函数名建立一个属性,属性值则为指向该函数所在堆内存地址的引用,如果存在,则会被新的引用覆盖。

3 . 检查当前上下文的变量声明,按代码顺序查找,将找到的变量提前声明,如果当前上下文的变量对象没有该变量名属性,则在该变量对象以变量名建立一个属性,属性值为undefined;如果存在,则忽略该变量声明

函数声明提前和变量声明提升是在创建变量对象中进行的,且函数声明优先级高于变量声明。

创建变量对象发生在预编译阶段,但尚未进入执行阶段,该变量对象都是不能访问的,因为此时的变量对象中的变量属性尚未赋值,值仍为undefined,只有进入执行阶段,变量对象中的变量属性进行赋值后,变量对象(Variable Object)转为活动对象(Active Object)后,才能进行访问,这个过程就是VO –> AO过程。

全局代码的上下文环境数据内容为:
普通变量(包括函数表达式),如: var a = 10; 声明(默认赋值为undefined)
函数声明,如: function fn() { } 赋值
this 赋值
如果代码段是函数体,那么在此基础上需要附加:
参数 赋值
arguments 赋值
自由变量的取值作用域 赋值
DeanTG commented 1 year ago

变量声明提升