JS高级 之 JavaScript的运行原理

目录

一、V8引擎的执行原理

1. Parse模块 

2. Ignition模块

3. TurboFan模块

二、JavaScript代码执行原理

1. 初始化全局对象 Global Object(GO)

2. 执行上下文 Execution Context Stack ( ECS )

3. VO对象(Variable Object)

三、全局代码执行过程

1. 执行前

​编辑

2. 执行后

四、函数代码执行过程

1. 执行前

2. 执行后

五、作用域和作用域链

1. 执行foo函数

​编辑

2. 执行bar函数


一、V8引擎的执行原理

JavaScript代码下载好后,是被浏览器的JS引擎执行的

V8引擎 : 一个强大的JavaScript引擎,是Google开源的高性能引擎,主要用于Chrome和Node.js

V8可以独立运行,也可以嵌入到任何C ++应用程序中 

1. Parse模块 

Parse模块会将JavaScript代码转换成AST(抽象语法树)

这是因为解释器并不直接认识JavaScript代码

2. Ignition模块

Ignition是一个解释器,会将AST转换成ByteCode(字节码)

  • 同时会收集TurboFan优化所需要的信息(比如函数参数的类型信息,有了类型才能进行真实的运算)
  • 如果函数只调用一次,Ignition会解释执行ByteCode
  • Ignition的V8官方文档 : Firing up the Ignition interpreter · V8

3. TurboFan模块

TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码

  • 如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过TurboFan转换成优化的机器码,提高代码的执行性能
  • 但是,机器码实际上也会被还原为ByteCode,这是因为如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型),之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码
  • TurboFan的V8官方文档 : Digging into the TurboFan JIT · V8

二、JavaScript代码执行原理

1. 初始化全局对象 Global Object(GO)

js引擎 = > 会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO)

  • 该对象 所有的作用域(scope)都可以访问
  • 里面会包含Date、Array、String、Number、setTimeout、setInterval等等
  • 其中还有一个window属性指向自己

2. 执行上下文 Execution Context Stack ( ECS )

js引擎 = > 内部有一个执行上下文栈(Execution Context Stack,简称ECS),它是用于执行代码的调用栈。

  • 在最开始的时候,全局的代码块为了执行会构建一个 Global Execution Context(GEC)
  • GEC会 被放入到ECS中 执行

GEC被放入到ECS中里面包含两部分内容 : 

  1. 在代码执行前,在parser转成AST的过程中,会将全局定义的变量、函数等加入到GlobalObject中,但是并不会赋值 => 变量的作用域提升
  2. 在代码执行中,对变量赋值,或者执行其他的函数

3. VO对象(Variable Object)

每一个执行上下文会关联一个VO(Variable Object,变量对象),变量和函数声明会被添加到这个VO对象中

当全局代码被执行的时候,VO就是GO对象了


三、全局代码执行过程

1. 执行前

  • 创建GEC全局执行上下文,存在一个VO
  • 创建GO对象,保存变量名,但不赋值,但如果遇到函数,会创建函数空间,同时指向该函数
  • 使其VO指向GO

2. 执行后

  • 开始依次执行代码,修改GO中的值


四、函数代码执行过程

在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Functional Execution Context,简称FEC),并且压入到EC Stack中

 因为每个执行上下文都会关联一个VO,那么函数执行上下文关联的VO是什么呢?

  • 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object)
  • 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数
  • 这个AO对象会作为执行上下文的VO来存放变量的初始化

1. 执行前

  • 创建FEC全局执行上下文,存在一个VO
  • 创建AO对象,保存变量名,但不赋值,但如果遇到函数,会创建函数空间,同时指向该函数
  • 使其VO指向AO

2. 执行后

  • 开始依次执行代码,修改AO中的值
  • 一旦函数代码执行完成后,FEC执行上下文出栈
  • 继续执行全局上下文


五、作用域和作用域链

当进入到一个执行上下文时,执行上下文也会关联一个作用域链(Scope Chain)

  • 作用域链是一个对象列表,用于变量标识符的求值
  • 当进入一个执行上下文时,这个作用域链被创建,并且根据代码类型,添加一系列的对象

1. 执行foo函数

2. 执行bar函数

猜你喜欢

转载自blog.csdn.net/a15297701931/article/details/125750847
今日推荐