写在前面:越来越多的毕业生加入了前端团队,可没有一个大学在学校里教过前端的课程(至少是我没听过),更别提浏览器的工作原理了,但是前端工程师接到最多的任务就是在浏览器里开发前端页面,那么了解浏览器工作原理,学会和浏览器打交道就成了学透前端的必经之路。下面从几步开始讲起~
第一步:了解进程与线程
官方解释:进程是cpu资源分配的最小单位,进程可以包含多个线程。 (浏览器就是多进程的) 线程是cpu调度的最小单位,同一进程下的各个线程之间共享程序的内存空间。 用一张图来解释:
第二步:浏览器都包含哪些进程
chrome => 窗口 => 任务管理器
浏览器会优化让多个页面公用同一个进程
第三步:浏览器内核(渲染进程)
第四步:GUI渲染线程
GUI就是来干这个事情的,如果修改了一些元素的颜色或者背景色,页面就会重绘(Repaint),如果修改元素的尺寸,页面就会回流(Reflow),当页面需要Repaint和Reflow时GUI都会执行,进行页面绘制。
第四步:JS引擎线程(如Chrome的V8引擎)
js引擎线程就是js内核,负责解析与执行js代码,也称为主线程。一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序(所以也称为单线程)。需要注意的是,js引擎线程和GUI渲染线程同时只能有一个工作,js引擎线程会阻塞GUI渲染线程(互斥原则)
<html>
<body>
<div id="div1"> a </div>
<script>document.getElementById('div1').innerHTML = 'b' </script>
<div id='div2'> div2 </div>
</body>
</html>
在浏览器渲染的时候遇到标签,就会停止GUI的渲染,然后js引擎线程开始工作,执行里面的js代码,等js执行完毕,js引擎线程停止工作,GUI继续渲染下面的内容。所以如果js执行时间太长就会造成页面卡顿的情况,这也是性能优化的点。
第五步:JS的单线程的由来
JavaScript 作为浏览器语言,主要用途就是与用户互动(操作Dom),而操作Dom就只能是单线程,否则就会引起复杂的同步问题,比如一个线程在某个Dom上添加内容,而另一个线程删除了这个节点,这时浏览器就不知道以哪个线程为准了。 为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。 单线程意味着一旦有代码报错或者循环调用(栈溢出)就会阻塞后面代码的执行,我们在浏览器中常常看到下面这样的报错,其实就是栈溢出导致的阻塞。