关于javascript:描述一下-V8-执行一段JS代码的过程

34次阅读

共计 1869 个字符,预计需要花费 5 分钟才能阅读完成。

前端相对来说是一个比拟新兴的畛域,因而各种前端框架和工具层出不穷,让人目迷五色,尤其是各大厂商推出 小程序 之后 各自制订规范 ,让前端开发的工作更加繁琐,在此背景下为了抹平平台之间的差别,诞生的各种 编译工具 / 框架 也不可胜数。但无论如何,想要赶上这些框架和工具的更新速度是十分难的,即便赶上了也很难产生本人的 技术积淀 ,一个更好的形式便是学习那些 实质的常识 ,抓住下层利用中不变的 底层机制,这样咱们便能轻松了解下层的框架而不仅仅是被动地应用,甚至可能在适当的场景下本人造出轮子,以满足开发效率的需要。

站在 V8 的角度,了解其中的执行机制,也可能帮忙咱们了解很多的下层利用,包含 Babel、Eslint、前端框架的底层机制。那么,一段 JavaScript 代码放在 V8 当中到底是如何执行的呢?

首先须要明确的是,机器是读不懂 JS 代码,机器只能了解特定的机器码,那如果要让 JS 的逻辑在机器上运行起来,就必须将 JS 的代码翻译成机器码,而后让机器辨认。JS 属于解释型语言,对于解释型的语言说,解释器会对源代码做如下剖析:

  • 通过词法剖析和语法分析生成 AST(形象语法树)
  • 生成字节码

而后解释器依据字节码来执行程序。但 JS 整个执行的过程其实会比这个更加简单,接下来就来一一地拆解。

1. 生成 AST

生成 AST 分为两步——词法剖析和语法分析。

词法剖析即分词,它的工作就是将一行行的代码分解成一个个 token。比方上面一行代码:

let name = 'sanyuan'
复制代码

其中会把句子分解成四个局部:

即解析成了四个 token,这就是词法剖析的作用。

接下来语法分析阶段,将生成的这些 token 数据,依据肯定的语法规定转化为 AST。举个例子:

let name = 'sanyuan'
console.log(name)
复制代码

最初生成的 AST 是这样的:

当生成了 AST 之后,编译器 / 解释器后续的工作都要依附 AST 而不是源代码。顺便补充一句,babel 的工作原理就是将 ES6 的代码解析生成ES6 的 AST,而后将 ES6 的 AST 转换为 ES5 的 AST, 最初才将 ES5 的 AST 转化为具体的 ES5 代码。因为本文着重论述原理,对于 babel 编译的细节就不开展了,举荐大家去读一读荒山的 babel 文章, 帮你关上新世界的大门: )

回到 V8 自身,生成 AST 后,接下来会生成执行上下文,对于执行上下文,能够参考上上篇《JavaScript 内存机制之问——数据是如何存储的?》中对于上下文压栈出栈过程的解说。

2. 生成字节码

结尾就曾经提到过了,生成 AST 之后,间接通过 V8 的解释器 (也叫 Ignition) 来生成字节码。然而 字节码 并不能让机器间接运行,那你可能就会说了,不能执行还转成字节码干嘛,间接把 AST 转换成机器码不就得了,让机器间接执行。的确,在 V8 的晚期是这么做的,但起初因为机器码的体积太大,引发了重大的内存占用问题。

给一张比照图让大家直观地感触以下三者代码量的差别:

很容易得出,字节码是比机器码轻量得多的代码。那 V8 为什么要应用字节码,字节码到底是个什么货色?

字节码是介于 AST 和 机器码之间的一种代码,然而与特定类型的机器码无关,字节码须要通过解释器将其转换为机器码而后执行。

字节码依然须要转换为机器码,但和原来不同的是,当初不必一次性将全副的字节码都转换成机器码,而是通过解释器来逐行执行字节码,省去了生成二进制文件的操作,这样就大大降低了内存的压力。

3. 执行代码

接下来,就进入到字节码解释执行的阶段啦!

在执行字节码的过程中,如果发现某一部分代码反复呈现,那么 V8 将它记做 热点代码 (HotSpot),而后将这么代码编译成 机器码 保存起来,这个用来编译的工具就是 V8 的 编译器 (也叫做TurboFan) , 因而在这样的机制下,代码执行的工夫越久,那么执行效率会越来越高,因为有越来越多的字节码被标记为 热点代码,遇到它们时间接执行相应的机器码,不必再次将转换为机器码。

其实当你听到有人说 JS 就是一门解释器语言的时候,其实这个说法是有问题的。因为字节码不仅配合了解释器,而且还和编译器打交道,所以 JS 并不是齐全的解释型语言。而编译器和解释器的 基本区别在于前者会编译生成二进制文件但后者不会。

并且,这种字节码跟编译器和解释器联合的技术,咱们称之为 即时编译, 也就是咱们常常听到的JIT

这就是 V8 中执行一段 JS 代码的整个过程,梳理一下:

  1. 首先通过词法剖析和语法分析生成 AST
  2. 将 AST 转换为字节码
  3. 由解释器逐行执行字节码,遇到热点代码启动编译器进行编译,生成对应的机器码, 以优化执行效率

对于这个问题的拆解就到这里,心愿对你有所启发。

正文完
 0