深入编译原理

作者: 深度剖析JavaScript | 来源:发表于2021-02-05 10:02 被阅读0次
    前言

    最近在看《YOU DON’T KNOW JS》一书,里面讲到JS的编译原理,只是宏观和简单的介绍了一下,于是自己写了此文,一来总结文中所讲的传统语言的编译和JS的编译原理,二来扩展一下我理解的编译原理

    传统编译语言的编译原理

    在传统的编译语言中,编译分三步

    1. 词法分析

    首先编译器会把代码分解成有意义的词法单元

    1. 语法分析

    接着,将词法单元组成的词法单元流(数组)解析成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为“抽象语法树”(Abstract Syntax Tree,AST

    1. 代码生成

    最后过程,将上面解析好的AST转换为可执行代码。说白了,就是通过某种方法可以将AST转化为一组机器指令

    我将上述过程绘制如下图:

    JS的编译原理

    JS引擎进行编译的步骤与传统编译语言非常相似,但比起那些编译只有三步的语言来说JS引擎要复杂的多。例如,在词法分析和代码生成阶段有特定的步骤来对运行性能进行优化,包括对冗余元素进行优化等

    而且,对于JS来说,大部分情况下编译发生在代码执行前的几微秒(甚至更短)的时间内

    简单来说,任何JS代码片段在执行前都要进行编译

    我理解的JS编译原理

    要理解JS的编译原理,其实得回顾JS是如何运行的?
    我将它JS运行分三个步骤

    1. 词法、语法分析
    2. 预编译
    3. 解释执行

    通常JS在执行代码前,系统会先执行词法和语法分析,通篇扫描一遍看是否有语法错误,有错误,程序终止,没有错误就会走到预编译环节

    预编译发生在函数执行前的前一刻,具体过程分四步:
    1.创建AO对象;(Active Object,执行期上下文)
    2.找形参和变量声明,将变量名和形参名作为AO对象的属性名,值为undefined
    3.将实参和形参相统一;
    4.在函数体里面找函数声明(不包括函数表达式),将函数声明的名作为AO对象的属性名挂起,值为该函数。

    在全局开始执行的前一刻,会发生全局预编译,生成的对象是GO(Global Object)

    预编译执行完才会开始解释执行代码,读一行执行一行,读一行执行一行。在读的过程,就会将代码变成可执行代码

    整个过程简单绘制如下:

    可以看到,与传统的编译相比,JavaScript引擎有个很大的特点就是多了一个预编译的环节。预编译之后也是通过引擎将代码解析成可执行代码,然后执行代码

    这就是JS引擎的运行过程和原理

    参考资料
    《YOU DON’T KNOW JS》

    相关文章

      网友评论

        本文标题:深入编译原理

        本文链接:https://www.haomeiwen.com/subject/ngqwtltx.html