浏览器的编译

Posted yanjieyan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器的编译相关的知识,希望对你有一定的参考价值。

从敲下一行JS代码到这行代码被执行,这中间发生了什么?

计算机不认识人类的语言,它只识别01010类似的二进制,也就是机器指令码。

开始的程序员都用它来写程序,可以想象当时的程序员有多痛苦,这种二进制码不易被人类记忆,后来发明了适合自己记忆各种高级计算机语言,包括JS。

但是计算机并不能直接识别JS语言,多以这里就需要一个中间媒介帮忙解释并且将其翻译成机器指令码给计算机执行,这个过程就叫编译。

而Chrome浏览器里面的V8引擎就是做这个事情的中介。但是并不止一家在做浏览器,所以市面上还有很多JS引擎。

主流浏览器 JS引擎
IE->Edge JScript(IE3.0-IE8.0)/cHAKRA(IE9+之后,查克拉,)
Chrome V8
Safari Nitro(4-)
FireFox SpiderMonkey(1.0-3.0)/TraceMonkey(3.5-3.6)/JaegerMonkey(4.0-)
Opera Linear A(4.0-6.1)/Linear B (7.0-9.2)/Futhark(9.5-10.2)/Carakan(10.5-)

因为JS引擎不同,前端理解的JS语法不同,就出现了兼容性问题。

Javascript引擎

是谁发明了javascript引擎?

任何人都可以。它只是分析代码翻译代码的工具。

V8S是最受欢迎的引擎之一,也是Chrome和Node使用的引擎。它是用C++编写的。

但是如果每个人都创造一个引擎,那场面就不可控制了。

因此为了规范,ECMA的标准就诞生了,该标准主要提供如何编写引擎和Javascript所有的功能规范。这就是新功能能在ES6,7,8上实现的原因。

同时,引擎也进行了更新来支持这些新功能,于是我们便可以在开发过程中检查了浏览器中js高级功能的可用性。

 

编译原理:

无论是哪种编译器,原理都差不多。

技术图片

 

 实际上上面的流程是协同运作的。

Interpreter 和 Compiler

通常,将代码转换成机器语言的方法有两种。

interpreter 逐行读取代码并立即执行

compiler 读取您的整个代码,进行优化,然后生成优化后的代码。

function num(a,b){
  return a+b  
}
for(let i=0;i<500;i++){
  num(1,1); 
}

上面的代码带用了num函数500次,interpreter接收上面的代码后,它将逐行读取并立即执行代码,直到循环结束。它的工作仅仅是实时地将代码转换为计算机能理解的内容。

如果这段代码的接受者是Compiler,它会先完整地读取整个程序,对我们要执行的代码进行分析,并生成电脑可以读取的机器语言。如果使用interpreter执行机器语言,则会获得与执行机器语言相同的结果。

它们唯一的区别在于转换的过程不尽相同:

interpreter逐行将源代码转换为灯小二机器代码;

compiler在一开始就将所有的源代码转换为机器代码。

interpreter的优点是无需等待编译即可立即执行代码。这对在浏览器中运行JS提供了极大的便利,因为所有用户都不想浪费时间在等待代码编译这件事上。但是,当有大量的JS代码需要执行时会运行地比较慢。

综上:interpreter可以立即开始执行代码,但不会进行优化。compiler虽然需要花费一些时间来编译代码,但是会生成对执行时更优的代码。

技术图片

考虑到编译器和解释器的优缺点,大多浏览器运用interpreter和compiler的结合,这就是JIT Compiler.

在编译执行的过程中,Parser是一种通过各种js关键字来识别,分析和分类程序各个部分的解析器。它可以区分代码是一个方法还是一个变量。

然后,AST抽象语法树基于Parser的分类构造树状结构。可以使用AST Explorer查看该树的结构。

随后将AST提供给interpreter生成bytecode.bytecode不是最底层的代码,但可以被执行。在此阶段,浏览器借助V8引擎执行bytecode进行工作,因此用户无需等待。

同时,Profiler将查找可以被优化的代码,然后将它们传递给Compiler。Compiler生成优化代码的同时,浏览器暂时用bytecode执行操作。并且,一旦Compiler生成了优化代码,优化代码则将完全替换掉临时的bytecode。

通过这种方式,可以充分利用interpreter和compiler的优点。interpreter执行代码的同时,Profiler寻找可以被优化的代码,Compiler则创建优化的代码。然后,将bytecode码替换为优化后的较为底层的代码,例如机器代码。这意味着性能将在逐步提高,同时不会阻塞执行的时间。

 

JS是但不完全是一门解释型语言。早期被创建的JS引擎‘SpiderMonkey".该引擎有一个interpreter来告诉浏览器该怎么执行代码。但是现在的引擎不仅包括了interpreter,还有compiler。我们的代码不仅可以被转换成bytecode,还可以被编译输出优化后的代码。因此,从技术上讲,这完全取决于引擎是如何实现的。

以上是关于浏览器的编译的主要内容,如果未能解决你的问题,请参考以下文章

导致资产预编译在heroku部署上失败的代码片段

如何有条件地将 C 代码片段编译到我的 Perl 模块?

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

损坏的顶点和片段着色器

Android 逆向Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )(代码片段

web代码片段