Open DeanTG opened 1 year ago
简而言之,执行上下文是对 JavaScript 代码执行环境的一种抽象,每当 JavaScript 运行时,它都是在执行上下文中运行。 (给执行上下文环境下一个通俗的定义——在执行代码之前,把将要用到的所有的变量都事先拿出来,有的直接赋值了,有的先用undefined占个空。)
执行栈,在其它编程语言中被叫做“调用栈”,是一种 LIFO(后进先出)栈的数据结构,被用来存储代码运行时创建的所有执行上下文。
当 JS 引擎开始执行第一行 JavaScript 代码时,它会创建一个全局执行上下文然后将它压到执行栈中,每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。
引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。
词法环境是一个包含标识符变量映射的结构
- 环境记录:存储声明的变量和函数( let, const, function,函数参数)
- 外部环境引用:作用域链
同样是一个词法环境,其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。
变量环境组件(VariableEnvironment) 是用来登记var function变量声明,词法环境组件(LexicalEnvironment)是用来登记let const class等变量声明。
变量对象的创建过程:
创建arguments对象,检查当前上下文中的参数,建立该对象的属性与属性值,仅在函数环境(非箭头函数)中进行,全局环境没有此过程
检查当前上下文的函数声明,按代码顺序查找,将找到的函数提前声明,如果当前上下文的变量对象没有该函数名属性,则在该变量对象以函数名建立一个属性,属性值则为指向该函数所在堆内存地址的引用,如果存在,则会被新的引用覆盖。
3 . 检查当前上下文的变量声明,按代码顺序查找,将找到的变量提前声明,如果当前上下文的变量对象没有该变量名属性,则在该变量对象以变量名建立一个属性,属性值为undefined;如果存在,则忽略该变量声明
函数声明提前和变量声明提升是在创建变量对象中进行的,且函数声明优先级高于变量声明。
创建变量对象发生在预编译阶段,但尚未进入执行阶段,该变量对象都是不能访问的,因为此时的变量对象中的变量属性尚未赋值,值仍为undefined,只有进入执行阶段,变量对象中的变量属性进行赋值后,变量对象(Variable Object)转为活动对象(Active Object)后,才能进行访问,这个过程就是VO –> AO过程。
全局代码的上下文环境数据内容为: | |
---|---|
普通变量(包括函数表达式),如: var a = 10; | 声明(默认赋值为undefined) |
函数声明,如: function fn() { } | 赋值 |
this | 赋值 |
如果代码段是函数体,那么在此基础上需要附加: | |
---|---|
参数 | 赋值 |
arguments | 赋值 |
自由变量的取值作用域 | 赋值 |
变量声明提升
link