【JS编译原理】V8执行JavaScript代码过程

文章目录

  • 前言
  • 一、编译器和解释器
  • 二、V8执行JavaScript代码过程
    • 1.生成AST(抽象语法树)
    • 2.生成字节码
    • 3.生成机器码
  • 总结


前言

相信大家对Babel已经不陌生了,Babel充斥在我们代码中的每个角落。比如:jsx转化成js,es6转化成es5…

一切需要代码转化的事都可以使用babel来做,但我们有没有想过,babel是怎么去进行代码转化的呢,它转化的过程中发生了什么,让我们一起来了解一下js的编译原理吧!

一、编译器和解释器

在了解之前,我们先来理解一下编译器和解释器的概念吧。

我们知道,我们所编写的代码是不能直接被机器识别的,需要转化成能被机器识别的机器语言。我们都知道,javascript是一门解释型语言,后端之王java是一门编译型语言,我们根据语言的执行流程可以分为解释型编译型。我们来看看他们的区别吧。

  • 解释型语言:需要将代码转换成机器码,但是和编译型的区别在于运行时需要转换。比较显著的特点是,解释型语言的执行速度要慢于编译型语言,因为解释型语言每次执行都需要把源码转换一次才能执行。
  • 编译型语言:在代码运行前编译器直接将对应的代码转换成机器码,运行时不需要再重新翻译,直接可以使用编译后的结果。

目前市面上有很多种 JS 引擎,其中比较现代的 JS 引擎就是 V8,它引入了 Java 虚拟机和 C++ 编译器的众多技术,和早期的 JS 引擎工作方式已经有了很大的不同。V8 是众多浏览器的 JS 引擎中性能表现最好的一个,并且它是 Chrome 的内核,Node.js 也是基于 V8 引擎研发的。

编译器解释器翻译代码流程如下:

编译器:
在这里插入图片描述
解释器:

在这里插入图片描述
大概可以描述为:

编译器:

  1. 在代码的编译中,编译器首先会把代码经过词法分析和语法分析成AST
  2. 然后经过优化变成可执行的文件
  3. 如果过程中有出现语法等错误,将会报错且不会生成可执行文件。

解释器:

  1. 在代码的编译中,解释器首先会把代码经过词法分析和语法分析成AST
  2. 解释器还会将AST进行词义分析生成字节码
  3. 根据字节码来生成程序,执行结果。

回归正题,让我们来看一看V8是怎么执行JavaScript代码的!

二、V8执行JavaScript代码过程

通常来说,我们可以将V8执行过程分为4个阶段:

  • Parse 阶段:V8 引擎负责将 JS 代码转换成 AST(抽象语法树)
  • Ignition 阶段:解释器将 AST 转换为字节码,解析执行字节码也会为下一个阶段优化编译提供需要的信息
  • TurboFan 阶段:编译器利用上个阶段收集的信息,将字节码优化为可以执行的机器码
  • Orinoco 阶段:垃圾回收阶段,将程序中不再使用的内存空间进行回收

1.生成AST(抽象语法树)

此阶段分为两个步骤:

  1. 词法分析:讲代码语句分割成最小的单元,称为token。例如:let a = 0;,分割成let,a,=,0,;五个单元,js会自动忽略空格单元
  2. 语法分析:讲token数据通过语法检测转换成AST,若语法不规范,则抛出错误

tips:babel的原理就是利用AST,把代码进行转换。Eslint也是通过将代码转化成AST,然后通过语法分析检测代码规范性的问题。

2.生成字节码

为什么要生成字节码?如果讲AST直接转换成机器码的话,会出现下面的问题:

  • 直接转换会带来内存占用过大的问题,因为将抽象语法树全部生成了机器码,而机器码相比字节码占用的内存多了很多
  • 某些 JavaScript 使用场景使用解释器更为合适,解析成字节码,有些代码没必要生成机器码,进而尽可能减少了占用内存过大的问题

字节码就是介于 AST 和机器码之间的一种代码。需要将其转换成机器码后才能执行,字节码可以理解为是机器码的一种抽象。Ignition 解释器除了可以快速生成没有优化的字节码外,还可以执行部分字节码。

3.生成机器码

在 Ignition 解释器处理完之后,如果发现一段代码被重复执行多次的情况,生成的字节码以及分析数据会传给 TurboFan 编译器,它会根据分析数据的情况生成优化好的机器码。再执行这段代码之后,只需要直接执行编译后的机器码,这样性能就会更好。

对于 TurboFan 编译器,它是 JIT(即时编译) 优化的编译器,因为 V8 引擎是多线程的,TurboFan 的编译线程和生成字节码不会在同一个线程上,这样可以和 Ignition 解释器相互配合着使用,不受另一方的影响。

总结

本篇博客借鉴了多位大佬的文章,每次阅读都会有新的理解,只有了解底层原理才能让自己在前端的道路上越走越远。

你可能感兴趣的:(技术文章,javascript,babel)