Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Execution Context #4

Open
DeanTG opened this issue Feb 1, 2023 · 8 comments
Open

Execution Context #4

DeanTG opened this issue Feb 1, 2023 · 8 comments

Comments

@DeanTG
Copy link
Owner

DeanTG commented Feb 1, 2023

link

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

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

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

执行上下文类型:

  • 全局执行上下文 —— 当 JS 引擎执行全局代码的时候,会编译全局代码并创建执行上下文,它会做两件事:1、创建一个全局的 window 对象(浏览器环境下),2、将 this 的值设置为该全局对象;全局上下文在整个页面生命周期有效,并且只有一份。
  • 函数执行上下文 —— 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
  • eval 执行上下文 —— 调用 eval 函数也会创建自己的执行上下文(eval函数容易导致恶意攻击,并且运行代码的速度比相应的替代方法慢,因此不推荐使用)

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

执行栈

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

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

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

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

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

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

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

执行上下文的创建阶段

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

词法环境

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

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

@DeanTG
Copy link
Owner Author

DeanTG commented Feb 2, 2023

变量环境

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

变量环境组件(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
Copy link
Owner Author

DeanTG commented Feb 2, 2023

变量声明提升

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant