JavaScript 编译原理
- 编译过程
- 词法分析
- 语法分析
- 代码生成
- 执行代码
编译过程
通常来说我们写的代码就是一长串的字符串(后面统称为长串的字符串),程序员在借助开发工具才有了格式一说。机器能能够识别的语言只有0和1,后面简称机器语言。JavaScript 引擎在代码与机器语言间承担“翻译”的工作
JavaScript 的编译过程包括词法分析,语法分析,代码生成及执行阶段。每个阶段都有一个产物供下一阶段使用。大致编译过程为:
长字符串 —> 词法分析分解为tocken —> 语法分析分解为AST —> interpreter转成字节码 —> compiler优化 —> 中间件 —> 转化为机器语言供计算机CPU执行
词法分析
计算机接收到的代码都是以长字符串的形式存在,需要对这些字符串进行拆分。首先需要进行词法分析。将整段代码分解成一个个词法单元,例如:
对于以下代码:
var a = 10;
分词器可能将代码分解为以下标记:
[ 'var', 'a', '=', '10', ]```
词法分析器会根据语言的语法规则来识别这些词法单元,并忽略掉那些对语言语法没有意义的字符(如空格、换行符等)。需要注意的是,分词与词法分析的区别在于,分词通常是无状态的,而词法分析可能涉及到有状态的解析规则。
语法分析
语法分析是词法分析的下一步,接收词法分析生成的词法单元序列,编译器将词法单元序列转换成一个由元素逐级嵌套所组成的代表程序语法结构的树,这个树被称为“抽象语法树”(Abstract Syntax Tree,AST)。
对于以下代码:
var a = 10;
词法分析后生成类似于以下描述的抽象语法树:
{ type: "string", len: 3, star: 0, end:3, name:var, }, { type: "string", len: 1, ...
AST是编译过程中非常重要的一个中间表示形式,它反映了程序的语法结构,但不包含程序的执行细节。
代码生成
代码生成是编译过程的最后一步。在这个阶段,编译器将AST转换为可执行代码。这个过程与具体的编程语言、目标平台等因素密切相关。对于JavaScript来说,由于它通常是在浏览器中执行的,因此代码生成器会生成可以在JavaScript引擎中执行的字节码或机器指令。
注意:JavaScript引擎在执行代码时并不是直接解释AST或字节码,而是通过一系列优化和解释执行过程来提高执行效率。
将AST转换成机器语言有两种方式
- interpreter:无需等待编译,立即执行,生成字节码,需要V8转译才能生成机器语言。缺点:逐行转换,代码多,性能比较低下
- compiler:一开始将代码转换成机器语言,不需要转译,性能高一些。缺点:开始的时候需要等待
注:现代浏览器解析执行JavaScript代码一般采用JIT方式,是一种结合interpreter和compiler优点,避免各自缺点的方式,即:把interpreter逐行执行,同时执行的过程中优化代码,compiler调用优化代码,同时字节码转换成机器码
执行代码
执行阶段是JavaScript代码生命周期的最后阶段。在这个阶段,JavaScript引擎会按照AST或优化后的代码结构来执行程序。由于JavaScript的单线程特性,在执行过程中会涉及到异步操作、事件循环和回调等机制的使用。