在 V8 出现之前,所有的 JavaScript 虚拟机所采用的都是解释执行的方式,「这是 JavaScript 执行速度过慢的一个主要原因」。而 V8 率先引入了即时编译(JIT)的双轮驱动的设计,这是一种权衡策略,混合编译执行和解释执行这两种手段,给 JavaScript 的执行速度带来了极大的提升。

另外,V8 也是早于其他虚拟机引入了惰性编译、内联缓存、隐藏类等机制,进一步优化了 JavaScript 代码的编译执行效率。V8 的出现,将 JavaScript 虚拟机技术推向了一个全新的高度。

接着通过下图,我们一起看看 V8 执行 JavaScript 代码的完整流程:

image-20220318111154805

V8 执行一段 JavaScript 代码所经历的主要流程包括:

  • 初始化基础环境;
  • 解析源码生成 AST 和作用域;
  • 依据 AST 和作用域生成字节码;
  • 解释执行字节码;
  • 监听热点代码;
  • 优化热点代码为二进制的机器代码;
  • 反优化生成的二进制机器代码。 V8 编译流水线并不复杂,但其中涉及到了很多技术,诸如 JIT、延迟解析、隐藏类、内联缓存、事件循环系统、垃圾回收机制等等。这些技术决定着一段 JavaScript 代码能否正常执行,以及代码的执行效率。对提的几个名词做个简单介绍:

「隐藏类(Hide Class)」:是将 JavaScript 中动态类型转换为静态类型的一种技术,可以消除动态类型的语言执行速度过慢的问题。熟悉 了 V8 的工作机制,在编写 JavaScript 时,就能充分利用好隐藏类这种强大的优化特性,写出更加高效的代码。

「惰性解析」:它目的是为了加速代码的启动速度,通过对惰性解析机制的学习,可以优化代码更加适应这个机制,从而提高程序性能。

「V8 事件循环系统」:事件循环系统和 JavaScript 中的难点异步编程特性紧密相关。JavaScript 是单线程的,JavaScript 代码都是在一个线程上执行,如果同一时间发送了多个 JavaScript 执行的请求,就需要排队,也就是进行异步编程。而 V8 事件循环系统会调度这些排队任务,保证 JavaScript 代码被 V8 有序地执行。因此也可以说,事件循环系统就是 V8 的心脏,它驱动了 V8 的持续工作。

「垃圾回收机制」:自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用对象),则没有被任何指针给指向,因此占用的内存也可以被回收掉。而 JavaScript 也是一种自动垃圾回收的语言。