JS 引擎解析过程
什么是 JS 引擎?
JavaScript 解析引擎是为「读懂」JavaScript 代码,并准确地给出代码运行结果的一段程序。
举个栗子:
1 | var a = 1 + 1; |
JavaScript 引擎所做的事情就是看懂(解析)这段代码,并将 a 的值变成 2
JS 的解释阶段
JS 是解释型语言,所以它无需提前编译,而是由解释器实时运行的
引擎对 JS 的处理过程:
1 | 1.读取代码,进行词法分析(Lexical analysis),然后讲代码分解成词元(token) |
最终计算机执行的就是机器码。
为了提高运行速度,浏览器一般采用即时翻译(JIT-JustIn Time compiler)
即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编码结果缓存(iniline cache)
这样会使整个程序的运行速度提升
而且对于不同的浏览器可能策略不同,有的浏览器为了省略了字节码的翻译过程,直接转为机器码(比如 chrome 的 v8)
总结:核心的 JIT 编译器可以将源码编译成机器码运行
JS 的预处理阶段
上述讲的解释器的整体过程,再讲一下在正式执行 JS 之前,还会有一个预处理阶段
- 变量提升
- 分号补全
- 处理变量冲突
- ···
分号补全
这个比较简单
1 | console.log('a') |
JS 预处理会在后面加上分号,因为 JS 解释器有一个「Semicolon Insertion」规则,他会按照一定规则,在适当的位置补充分号
规则(不全):
- 当有换行符的时候(包括含有换行符的多行注释),并且下一句 token 没有根前面的语法匹配时,自动添加分号。
- 当有}时候,如果缺少分号,会添加分号
- 程序源代码结束是,如果缺少分号,会补分号。
最终
1 | console.log('a'); |
举一个反例
1 | function b() { |
可能你想输入的结果是:
1 | {a: 'a'} |
但是由于分号补全机制,最后会变成:
1 | function b(){ |
运行以后就是
1 | undefined |
变量提升
在执行过程中,可能开头没有定义变量或者函数,但是往往并没有报错。
其中包括函数提升和变量提升
1 | a = 1; |
由于变量提升,最终结果,2 个 b()都会执行,a 会被赋值。