探索V8引擎

384 阅读4分钟

JavaScript目前可以在node环境和浏览器中执行, 我们编写的JavaScript代码是如何被计算机理解的?
JavaScript 是一门高级语言,但是最终计算机能理解只有1和0。那么我们编写的代码是如何被计算机理解的呢?掌握所学编程语言的基础知识将让您能编写出更好的代码。

JavaScript 引擎

分析我们的代码并将其翻译的另一种语言的工具。

JavaScript引擎的主要工作就是解析我们的js代码,使计算机可以理解我们编写的代码。JavaScript 引擎是一种用于将我们的代码转换为机器可读语言的引擎。不仅仅是 JavaScript ,其他所有编程语言都需要一个类似的引擎,来将这些“胡言乱语”转换成对计算机有意义的语言。
目前常见的JavaScript引擎:
Chrome: blink(V8)
IE: Trident
firefox: Gecko
Safari: webkit
Opera: blink

V8 是最受欢迎的 JavaScript 引擎之一,也是 Chrome 和 NodeJS 使用的引擎。它是用 C++(一种底层语言)编写的。任何人都可以写一个js引擎去处理js, 如果这些引擎没有一个统一的规范,每个人都创造一个引擎,那场面就不可收拾了。因此ECMA 的标准诞生了,该标准主要提供如何编写引擎和 JavaScript 所有功能的规范。

JavaScript 是如何工作的?

引擎解析javascript代码的大致流程

JavaScript V8 Engine

上图就是 JS Engine 内部的工作流程。我们输入的代码将通过以下阶段:

  1. Parser
  2. AST
  3. Interpreter 生成 ByteCode
  4. Profiler
  5. Compiler 生成优化后的代码

通常,将代码转换成机器可读语言的方法有两种。Interpreter和Compiler

  • Interpreter 逐行读取代码并立即执行。
  • Compiler 读取您的整个代码,进行一些优化,然后生成优化后的代码。
    function num(a,b){
        return a+b;
    }
    for(let i = 0; i < 999; i++){
        num(1+1);
    }

当引擎开始执行这段代码时,Interpreter首先开始工作。 Interpreter解析这段代码并立即将代码翻译成机器码,并且立即输出结果,它的工作仅仅是实时地将代码转换为我们的计算机可以理解的内容并执行。 Compiler解析这段代码时,发现for循环中在循环调用 num(1+1)并一直返回固定的结果, Compiler在将此代码转化成机器码时对此代码优化。

Interpreter 和 Compiler 都将源代码转换为机器语言,它们唯一的区别在于转换的过程不尽相同。

Interpreter 和 Compiler 的优缺点

Interpreter 的优点是无需等待编译即可立即执行代码。这对在浏览器中运行 JS 提供了极大的便利,因为所有用户都不想浪费时间在等待代码编译这件事上。但是,当有大量的 JS 代码需要执行时会运行地比较慢。还记得上面例子中的那一小段代码吗?代码中执行了1000次函数调用。函数 num 被调用了1000次,但他的输出保持不变。但是 Interpreter 还是逐行执行,会显得比较慢。

在同样的情况下,Compiler 可以通过用2代替循环(因为 num 函数每次都是执行1 + 1)来进行一些优化。Compiler 最终给出的优化代码可以在更短的时间内执行完成。

综上所述,Interpreter 可以立即开始执行代码,但不会进行优化。Compiler 虽然需要花费一些时间来编译代码,但是会生成对执行时更优的代码。

Profiler

Profiler 将查找可以被优化的代码,然后将它们传递给 Compiler。Compiler 生成优化代码的同时,浏览器暂时用 ByteCode 执行操作。并且,一旦 Compiler 生成了优化代码,优化代码则将完全替换掉临时的 ByteCode。
通过这种方式,我们可以充分利用 Interpreter 和 Compiler 的优点。Interpreter 执行代码的同时,Profiler 寻找可以被优化的代码,Compiler 则创建优化的代码。然后,将 ByteCode 码替换为优化后的较为底层的代码,例如机器代码。

JavaScript 是一门解释型语言吗?

js是一个解释型和编译型并存的语言, 这也是js在V8下很快的原因之一。 立即执行代码会被解释器立马执行, 同时Profiler会对代码进行优化,再将优化后的代码交给编译器Compiler进行代码转化。