这是我参与更文挑战的第14天,活动详情查看: 更文挑战
前言
前段时间在看小黄书,里头讲了JS
的编译原理,并提到了JS
引擎,出于好奇,我想去了解相关方面的知识。查阅了大量资料后,我将知识点归纳吸收,便有了此文
为了方便阅读,我将文章分成一下几部分
什么是JS引擎
关于什么是JS引擎,我觉得结合生活中的例子会很好理解!
以生活中的汽车为例,汽车需要动,能让汽车动起来的那个东西就是引擎,如V8发动机。如果没有引擎,那仅仅是一堆废铜烂铁。
而JS引擎也是一样,就是让JS动起来的东西。
为了体现我的专业,引入百度百科对它的定义
可以看到,JS
引擎本质是一个虚拟机或者说是一个程序,只是这个程序能处理我们的JS代码,让我们写JS代码动起来,从而发挥代码的威力。
那引擎具体做了哪些工作呢?
简单总结,JS
引擎可以将 JS
代码编译为不同 CPU
对应的汇编代码,而且还负责执行代码、分配内存以及垃圾回收等工作
常见的JS引擎有哪些
其实这也是我最开始学写篇文章的初衷,我在网上查阅了很多资料,但是发现文章都比较陈旧,而且各个引擎出现的时间杂乱无章,于是我希望自己可以按照引擎出现的时间线进行整理
下面按照各大引擎大致出现的顺序进行排列
-
Mozilla的
SpiderMonkey
引擎,是第一款JavaScript引擎,早期用于 Netscape Navigator,现时用于 Mozilla Firefox。是用C语言实现的,还有一个Java版本叫Rhino;Rhino
引擎由Mozilla基金会管理,开放源代码,完全以Java编写,用于 HTMLUnit;而后TraceMonkey
引擎是基于实时编译的引擎,用于Mozilla Firefox 3.5~3.6版本;JaegerMonkey
:结合追踪和组合码技术大幅提高性能,用于Mozilla Firefox 4.0以上版本 -
Apple的
JavaScriptCore
,简称JSC,开源,用于webkit内核浏览器,如 Safari ,2008 年实现了编译器和字节码解释器,升级为了SquirrelFish
。苹果内部代号为Nitro
的 JavaScript 引擎也是基于 JSC引擎的。至于具体时间,JSC是WebKit默认内嵌的JS引擎,而WebKit诞生于1998年,Nitro
是为Safari 4编写,Safari 4是2009年6月发布。 -
Opera的
LinearA
:用于Opera4.0到6.1,Opera4于2000年6月发布;LinearB
:用于Opera7.0到9.2,Opera7于2003年6月发布;Futhark
:用于Opera9.5到10.2,Opera9.5于2008年6月发布;Carakan
:用于Opera10.5.及以上 2009年12月 -
Tamarin
引擎,由Adobe Labs编写,Flash Player 9所使用的引擎,大概时间2006年6月 -
2008年9月,Google的
V8
引擎第一个版本随着Chrome的第一个版本发布。V8
引擎用 C++编写,由 Google 丹麦开发,开源。除了Chrome,还被运用于Node.js以及运用于Android操作系统等 -
Microsoft 的
Chakra
,译名查克拉,用于IE9、10、11和Microsoft Edge,IE9发布时间2011年3月 -
JerryScript
引擎 , 三星推出的适用于嵌入式设备的小型 JavaScript 引擎,2015年开源 -
Nashorn
引擎,从 JDK 1.8 开始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成为 Java 的嵌入式 JavaScript 引擎,JDK1.8发布于2014年 -
QuickJS
引擎, 2019 年 7 月发布 -
Hermes
引擎,Facebook在Chain React 2019 大会上发布的一个崭新JavaScript引擎,用于移动端React Native应用的集成,开源
注:
- 上述内容参考了大量资料所得,并不保证一定精准
- 由于有些引擎找不到何时发布的具体时间,于是我把该引擎最早被应用的时间表示其发布时间
了解什么是JS引擎,也梳理常见的JS引擎,下面我们来看看引擎是如何运行JS代码的:以V8为例
V8引擎如何运行JS代码
首先我们简单来了解一下V8引擎
关于V8
V8
引擎是使用C++
编写的,由Google
开源的JavaScript
和WebAssembly
引擎。V8
第一个版本随着第一个版本的Chrome
于2008
年9
月2
日发布。
V8因为它的高性能被很多人青睐,于是常见的如
Chrome
浏览器的JS
引擎是V8
Nodejs
的运行时环境是V8
electron
的底层引擎也是V8
那V8具体都做了哪些工作呢?
V8主要职责
简单来说,V8
是一个接收JavaScript
代码,编译代码然后执行C++
程序,编译后的代码可以在多种操作系统多种处理器上运行。其主要职责:
- 编译和执行
JS
代码 - 处理调用栈
- 内存分配
- 垃圾回收等
下面主要来看,V8如何编译和执行JS
V8如何编译和执行JS代码
一般来说,JS
引擎在编译和执行代码都会用到三个重要的组件:
解析器parser
负责将JS
源代码解析成抽象语法树AST
,如下:
JS代码变成AST的样子,你可以移步到ASTExplorer去看
解释器interpreter
解释器负责将AST
解析成字节码bytecode
,并可以将解析成的bytecode
解释执行
编译器compiler
编译器负责编译出运行更加高效的机器代码
但是在V8
早期,在5.9
版本以前,是没有解释器,但有两个编译器,其编译流程如下
parser
解释器生成抽象语法树AST
compiler
编译器Full-codegen
基准编译器 直接生成机器码- 运行一段时间后,由分析器线程优化
js
代码 compiler
编译器CrankShaft
优化编译器 重新生成AST
提升运行效率
这样设计的缺点
- 机器码会占用大量的内存
- 缺少中间层机器码,无法实现一些优化策略
- 无法很好的支持和优化
JS
的新语特性,无法拥抱未来
正因为存在以上问题,新版本的V8流程上有所优化,流程如下
parser
解析器 生成AST
抽象语法树interpreter
解释器Ignition
生成byteCode
字节码 并直接执行- 清除
AST
释放内存空间 - 得到
25% - 50%
的等效机器代码大小 compiler
运行过程中,解释器收集优化信息发送给编译器TurboFan
- 重新生成机器码
- 有些热点函数变更会由优化后的机器码还原成字节码 也就是
deoptimization
回退字节码操作执行
优化点:
- 值声明未调用,不会被解析生成
AST
- 函数只被调用一次,
bytcode
直接被解释执行,不会进入到编译优化阶段 - 函数被调用多次,
Igniton
会收集函数类型信息,可能会被标记为热点函数,可能被编译成优化后的机器代码
好处:
- 由于一开始不需要直接编译成机器码,生成了中间层的字节码,从而节约了时间
- 优化编译阶段,不需要从源码重新解析,直接通过字节码进行优化,也可以
deoptimization
回退操作
以上就是本次关于JS引擎的所有内容!如果有误,欢迎留言告知,也欢迎点赞支持!
end
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!