说起javascript编译,很多人都会想到V8,但其实不仅仅是V8,各个浏览器厂商都有自己的javascript引擎,比如Chrome的V8, Firefox的SpiderMonkey, Safari的JavaScriptCore, Edge的Chakra等等,这些引擎都是编译javascript的核心。
javascript引擎会把我们写的javascript代码“编译”成机器可执行的指令,执行速度很快。下面我们以V8为例,来看看javascript引擎的编译过程。
function foo(a) { return a + 1; }
在V8中,上述javascript代码的编译分为如下几个步骤:
首先,V8会对代码进行AST(抽象语法树)解析,把代码转换成一棵树形结构,以便后序处理。例如:
Program └─FunctionDeclaration ├─Identifier └─BlockStatement └─ReturnStatement └─BinaryExpression ├─Identifier └─NumericLiteral
然后,V8会将AST转换成字节码(bytecode),这个过程通常被称作预编译(parse), 将javascript的语法解析成指令序列,可以理解为一个指令集。
0x0001 LOAD_ARG 0 0x0002 LOAD_CONSTANT 0 0x0003 BINARY_OP + 0x0004 RETURN
接着,V8通过JIT编译器(JIT Compiler)将字节码编译成本地的机器代码(x86、ARM等),即代码执行速度极快的形式。在V8中,将字节码编译成机器码,并同时进行调用优化和内联缓存优化。在JIT编译器中,V8会对常用代码进行优化,通过编译器优化让代码执行的更快,例如,对于常用的语法糖函数(如arr.map, arr.reduce)等,V8会编译成高度优化后的机器码。
此外,V8引擎还扮演了一个内存分配的角色。在javascript代码的执行过程中,需要创建对象、数组等复杂数据结构。V8在内部实现中会对这些对象在内存中的布局、分配进行了很多优化。
总的来说,javascript引擎编译过程,是将我们写的javascript代码转化为可执行的本地机器码的过程。这样就能让我们的程序得到更快的执行速度。