浏览器的核心分为两个部分:渲染引擎和JavaScript解释器(引擎)
1、渲染引擎:
主要作用:将网页代码渲染为用户视觉效果可以感知的平面文档
Firefox:Gecko引擎
Safari:Webkit引擎
Chrome:Blink引擎
IE:Trident引擎
Edge:EdgeHTML引擎
渲染引擎处理网页,通常分为四个阶段:1、解析代码:HTML代码解析为DOM,CSS代码解析为CSSOM;2、对象合成:将DOM和CSSOM合成一颗渲染树(render tree);3、布局:计算出渲染树的布局流(layout flow);4、绘制:将渲染树根据布局流绘制到屏幕。以上四个阶段并非严格按顺序执行的,往往第一步还未执行完,第二和第三步就已经开始了。所以会看到HTML代码还未下载完,浏览器就已经显示部分内容了。
2、重流和重绘:
渲染树转换为网页布局,称为“布局流”(flow),布局显示到页面的这个过程,成为“绘制”(paint)。它们都具有阻塞效应。并且会耗费很多时间和计算资源。页面生成以后,脚本操作和样式表操作,都会触发“重流”(reflow)和“重绘”(repaint)。用户的互动也会触发重流和重绘,比如设置了鼠标悬停(a:hover)效果、滚动、在输入框中输入文本、改变窗口大小等等。
重流和重绘并不一定会一起发生,重流必定导致重绘,重绘不一定需要发生重流。比如改变元素颜色,只会导致重绘,而不会导致重流;简单的来说,改变元素的布局,则会发生重流,也就是对布局流做重新的计算。当然也会发生重绘。
大多数情况下,浏览器会智能判断,将重流和重绘只限制到相关的子树,最小化所耗费的代价,而不会全局重新生成网页。
作为开发者,应该尽量设法降低重绘的次数和成本。比如,尽量不要变动高层的DOM元素,而以底层DOM元素的变动替代;再比如,重绘table布局和flex布局,开销都会比较大。当然浏览器也会积累DOM变动,然后一次执行。
关于减少重绘的优化技巧:
1、读取DOM或者写入DOM的操作,尽量写在一起,不要混杂。即不要读取一个节点,立即修改这个节点,接着再读取一个DOM节点。
2、缓存DOM信息。
3、不要一项一项地改变样式,而使用CSS class一次性的改变样式。
4、使用documentFragment操作DOM。
5、动画使用absolute定位或fixed定位,这样可以减少对其他元素的影响。
6、只在必要的时候显示隐藏元素。
7、使用window.requestAnimationFrame(),因为他可以把代码推迟到下一次重流执行,而不是立即要求页面重流。
8、使用虚拟DOM(virtual DOM)库。这样的方式还可以简化节点的操作和继承层次。现在很多框架都采用这种方式。
3、JavaScript引擎:
主要作用:读取网页中的javascript代码,对其进行处理并运行。
javascript是一种解释型语言,也就是它不需要编译,有解释器实时运行。这样的好处是运行和修改都比较方便,刷新页面皆可以重新解释执行;缺点是每次执行都需要重新调用解释器,系统开销较大,运行速度慢于编译型语言。为了提高运行速度,目前浏览器都javascript进行一定程度的编译,生成类似字节码(bytecode)的中间代码,以提高运行速度。
早期浏览器对javascript处理分为以下几个阶段:(即编译原理)
1、读取代码,进行词法分析(Lexical),将代码分解成词元(token)。
2、对词元进行语法分析(parsing),将代码整理成“语法树”(syntax tree)。
3、进行语义分析,使用“翻译器”将代码转为字节码(bytecode)。
4、使用“字节码解释器”(bytecode interpreter)将字节码转换成机器码。
但是,逐行解释将字节码转换成机器码,是很低的效率。为了提高运行速度,现代浏览器改为采用“即时编译”(Just In Time Compiler,缩写JIT),即字节码只在运行时编译,用到哪一行就编译哪一行,并且把编译结果缓存(inline cache)。通常,一个程序被经常用到的,只是其中一小部分代码,有了缓存的编译结果,整个程序的运行速度就会提升。字节码不能直接运行,而是运行在一个虚拟机之上(Virtual Machine)之上,一般也把虚拟机成为javscript引擎。并非所有的js引擎都是将字节码编译成机器码运行的,有的引擎是基于源码编译成机器码运行,即只要有可能,就直接通过JIT编译器将源码编译成机器码运行,省略字节码步骤。这一点与其他采用虚拟机的语言不相同(java等)。这样做的目的,只为了尽可能的优化代码,提高性能。下面介绍现代最常见的js引擎:
1、IE:Chakra
2、Safari: Nitro、JavaScript Core
3、Opera:Carakan
4、Chrome:V8
以上对浏览器的核心就解释到这里,更多的参考阮一峰老师的javascript标准参考教程