莱芜高新区管委会网站长沙免费建站网络营销
前言
JavaScript到底是什么类型语言?就算是JavaScript老司机也可能会直言当然是解释型语言了,但是当我们深入JavaScript并研究 V8引擎、JIT编译器时,将会发现原来不是那么回事,接下来我将带你剖析JavaScript到底是什么类型的语言。
对JavaScript语言类型的疑问点?
最初,网上的大部分JavaScript教程,都会给你说JavaScript是解释型语言,如果我们细想的话,就会对此产生疑问:
- 如果JavaScript是解释型语言那为什么会有变量提升(hoisting),待会解释变量提升
- JIT(即时编译)会对代码进行优化(同时创建编译版本),这是解释型无法做到的
我们对上述问题进行剖析
什么是解释型语言?
解释型语言编写的程序在每次运行时都需要通过解释器对程序进行动态解释和执行
- 优点:可移植好,因为只需要系统有JavaScript解释器就可以运行,无需其他系统库支持
- 缺点:执行速度慢,因为相比直接执行,多了一个翻译过程
什么是编译型语言?
编译型语言的程序只需要通过编译器编译后,可以直接执行,不需要再次“翻译”;
- 优点: 执行速度快
- 缺点: 可移植性差,因为编译需要对操作系统的库做出链接,所以程序运行时需要用到特定的系统库
什么是变量提升?
如果你有编写过js代码,我觉得你应该已经知道了JavaScript的变量提升。在我们声明的变量将会被提升到顶部,也就是”undefined“,这是你应该会有疑惑,明明有值啊,怎么会是”undefined“,是笔者误导还是JavaScript引擎偷偷执行了两次?我们看下JavaScript处理声明语句的过程:
JavaScript 声明语句过程
- 当V8引擎执行具体代码上下文(函数),将对代码进行 “词法分析” 或者 “分词”, 如: “foo = 2”,将被分割成 “foo ”=“ ”2“的词法单元(atomic token)
- 当引擎对当前整个作用域分析完成,然后会将 token 解析翻译成一个 AST(抽象语法树)
- 每当引擎遇到声明语句,就会将变量分配内存,但不会修改源代码,而是将变量提升并默认值 ”undefined“,并传递到作用域(scope)中并创建一个绑定
- 当需要赋值时,引擎首先通过作用域(scope)查找绑定,如果作用域中没有找到就往上查询,直到找到为止
- 接下来引擎将会生成CPU可执行的机器码
- 最后,代码执行完成
所以,变量提升只不过是解释器从执行作用域的上下文中查找变量值。


JavaScript中的JIT(即时编译)
JIT(just in time)即 即时编译,简单解释就是一个程序在执行的时候创建并运行了全新的机器可识别的代码,而并你写的源代码。
JIT编译器并不是JavaScript特有,在其它语言(如:Java中的JVM)中也有执行前编译代码的机制。
我们看下一段代码,能够更加直观的了解编译型和解释型


编译型语言: 在执行循环”sum += 1“时,已经编译为机器码,机器码将直接运行100次。
解释型语言: 在执行循环”sum += 1“时,会在循环的过程中执行,也就是会编译100次。
这也是V8引擎为什么那么快的原因。
总结
现在我们已经了解了 JavaScript 运行中发生什么了,对JavaScript是编译型还是解释型语言也清晰了。