前些天,正值期末考试阶段,对于大学生的考试,dddd。但是,在“复习”计算机组成原理的时候,看到了这样一句话
编译程序是先完整编译后运行的程序,如 C++,C 等;解释程序是一句一句翻译且边翻译边执行的程序 ,如 JavaScript,Python 等;
JavaScript 是解释型语言这一点,在开始学习 JavaScript 的时候就已经有所了解。但是后面的半句却让我心生疑惑,因为前段时间看过一部分李兵老师关于浏览器的课程,老师解释的是,JavaScript 的执行机制是先编译后执行。啊这?
向群里的小伙伴表达了疑惑,都说这里面关系到底层原理,有些复杂了,好奇心驱动下,网上冲浪找寻资料,斗胆梳理一下,如有错误,望指点!
1.计算机系统的层次
1.1语言级别
计算机编程语言可以分为三个级别:
- 机器语言:由于硬件的原因,像灯泡只有开和关两种状态,计算机可以理解为很多个灯泡组成的复杂系统,所以计算机也只能理解 0 和 1 两种状态。机器指令由一串二进制数表示,例如
00011101
,一条指令就对应计算机可以正确执行的一种命令, 机器语言是机器指令的集合。 - 汇编语言:是一种低级的符号语言,汇编的主体是汇编指令像 ADC(带进位加法),SUB(减法) 这种,汇编指令可以认为是机器指令的助记符。
- 高级语言,像 JavaScript,Java,C,C++ 等,高级语言是便于人类理解的,你一看到一种语言里面的关键词,就能大概知道它是在哪方面的发挥作用的
机器语言是计算机唯一可以直接识别和执行的语言。不管是哪一种高级语言,都要经过翻译成机器语言才能被计算机执行,但是呢,翻译也有两种。
1.2 编译与解释
编译是将高级语言一次全部翻译成目标代码(机器语言),然后 CPU 直接执行,每次执行程序的时候,只执行目标代码,只要源程序不变就无需重新编译。跨平台性较低,效率较高
解释是将源程序的一条高级言翻译成目标代码(机器语言),并立即执行,然后再去翻译下一条语句并执行,跨平台性较高,效率较低。
2. JavaScript引擎
2.1 JavaScript 引擎的作用
JavaScript 引擎早期直接将 JavaScript 源代码解释成没有优化的二进制机器码,这样会有两个问题:
- 解释时间长,
- 二进制代码占用更多内存
随着对用户体验的要求不断提高,技术的不断升级,现代 JavaScript 引擎已经有了很大的进步。
2.2 现代 JavaScript 引擎
Java 语言的字节码方案得到了业界内认可,其他语言充分借鉴,其中就包括我们的 JavaScript。
2.2.1 Java字节码
Java采用虚拟机技术支持跨平台特性,一套代码可以在多个系统上运行。
2.2.2 JavaScriptCore 引擎
JavaScriptCore 引擎是 WebKit 中默认的引擎,使用 WebKit 的主要两个浏览器 Sfari 和Chromium(Chorme 的开源项目)。
2.2.3 v8引擎
v8 用c++编写,用于 Chrome 和 Node.js ,编译 / 执行 JavaScript 代码。
JavaScript 引擎相关知识,稍稍复杂,以后有机会再进行学习总结。
不过不同引擎对于 JavaScript 的优化方案都略有不同,但是现在大多都融入了字节码和 JIT 技术
发现某个方法或代码块运行特别频繁的时候,就会认为这是“热点代码”(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"
}
复制代码
参考: