计组考试引发 JavaScript 编译的思考

前些天,正值期末考试阶段,对于大学生的考试,dddd。但是,在“复习”计算机组成原理的时候,看到了这样一句话

编译程序是先完整编译后运行的程序,如 C++,C 等;解释程序是一句一句翻译且边翻译边执行的程序 ,如 JavaScript,Python 等;

JavaScript 是解释型语言这一点,在开始学习 JavaScript 的时候就已经有所了解。但是后面的半句却让我心生疑惑,因为前段时间看过一部分李兵老师关于浏览器的课程,老师解释的是,JavaScript 的执行机制是先编译后执行。啊这?

向群里的小伙伴表达了疑惑,都说这里面关系到底层原理,有些复杂了,好奇心驱动下,网上冲浪找寻资料,斗胆梳理一下,如有错误,望指点!

1.计算机系统的层次

1.1语言级别

计算机编程语言可以分为三个级别:

  1. 机器语言:由于硬件的原因,像灯泡只有开和关两种状态,计算机可以理解为很多个灯泡组成的复杂系统,所以计算机也只能理解 0 和 1 两种状态。机器指令由一串二进制数表示,例如 00011101,一条指令就对应计算机可以正确执行的一种命令, 机器语言是机器指令的集合。
  2. 汇编语言:是一种低级的符号语言,汇编的主体是汇编指令像 ADC(带进位加法),SUB(减法) 这种,汇编指令可以认为是机器指令的助记符。
  3. 高级语言,像 JavaScript,Java,C,C++ 等,高级语言是便于人类理解的,你一看到一种语言里面的关键词,就能大概知道它是在哪方面的发挥作用的

image-20210710104611041.png

机器语言是计算机唯一可以直接识别和执行的语言。不管是哪一种高级语言,都要经过翻译成机器语言才能被计算机执行,但是呢,翻译也有两种。

1.2 编译与解释

编译是将高级语言一次全部翻译成目标代码(机器语言),然后 CPU 直接执行,每次执行程序的时候,只执行目标代码,只要源程序不变就无需重新编译。跨平台性较低,效率较高

解释是将源程序的一条高级言翻译成目标代码(机器语言),并立即执行,然后再去翻译下一条语句并执行,跨平台性较高,效率较低。

2. JavaScript引擎

2.1 JavaScript 引擎的作用

JavaScript 引擎早期直接将 JavaScript 源代码解释成没有优化的二进制机器码,这样会有两个问题:

  • 解释时间长,
  • 二进制代码占用更多内存

随着对用户体验的要求不断提高,技术的不断升级,现代 JavaScript 引擎已经有了很大的进步。

2.2 现代 JavaScript 引擎

Java 语言的字节码方案得到了业界内认可,其他语言充分借鉴,其中就包括我们的 JavaScript。

2.2.1 Java字节码

未命名文件.jpg

Java采用虚拟机技术支持跨平台特性,一套代码可以在多个系统上运行。

2.2.2 JavaScriptCore 引擎

JavaScriptCore 引擎是 WebKit 中默认的引擎,使用 WebKit 的主要两个浏览器 Sfari 和Chromium(Chorme 的开源项目)。

2.2.3 v8引擎

v8 用c++编写,用于 Chrome 和 Node.js ,编译 / 执行 JavaScript 代码。

JavaScript 引擎相关知识,稍稍复杂,以后有机会再进行学习总结。

不过不同引擎对于 JavaScript 的优化方案都略有不同,但是现在大多都融入了字节码和 JIT 技术

未命名文件(1)(1).jpg

发现某个方法或代码块运行特别频繁的时候,就会认为这是“热点代码”(Hot Spot Code)。然后 JIT 会把部分“热点代码”编译成本地机器相关的机器码,并进行优化,然后再把编译后的机器码缓存起来,以备下次使用。提高执行速度

所以 JavaScript 引擎的作用是什么?就是对代码进行优化,使得解释执行的效率更加高,最终还是要转化为机器码,由 CPU 执行的。

3 解决问题

说了一大堆(可能还没有说清楚),JavaScript 执行到底是怎样的?先编译后执行?

一段 JavaScript 代码运行起来,大概可以分为三个步骤:

  • 词法分析和语法分析(这里应该是会生成AST抽象语法树)

  • 预编译(这里的预编译就是李兵老师说的先编译后运行中的编译,这里会由变量提升,执行上下文。词法环境等相关知识,之前的一篇博客由总结)

  • 解释执行(坚持一个观点,高级语言不管经历了啥,最终都要转化成机器语言,而机器语言都是由 CPU 执行的,所以JavaScript 归为解释型语言的一点就是,预编译后它是边解释边执行的)

词法分析:将语句分割成各种类型的代码块(词法单元),例如,var a = 1 可以拆成 var、a、=、1,零散的词法单元会组成一个词法单元流。

语法分析:词法单元流被解析成 AST(抽象语法树),像下面这样

{
    "type": "Program",
    "body": [
        {
            "type": "VariableDeclaration",
            "declarations": [
                {
                    "type": "VariableDeclarator",
                    "id": {
                        "type": "Identifier",
                        "name": "a"
                    },
                    "init": {
                        "type": "Literal",
                        "value": 1,
                        "raw": "1"
                    }
                }
            ],
            "kind": "var"
        }
    ],
    "sourceType": "script"
}
复制代码

参考:

理解Javascript执行过程

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享