Js基础学习笔记(一):Js运行机制相关
Js运行机制相关
一、进程与线程
进程如仓库(有独立的地址空间),线程如运输货车,
每个进程可以有多个线程。
二、渲染进程(前端重点需要关注)
配合下面思维导图,图片来自这篇文章:https://www.jianshu.com/p/daa9a815a643,
大家可以在这篇文章的图片上,右键——在新标签页中打开图片,以此来查看高清图片。
浏览器包括4类进程:
1.主进程(Browser进程):浏览器只有一个主进程,负责资源下载、界面展示等主要基础功能;
2.GPU进程:负责3D图示绘制,最多一个;
3.第三方插件进程:负责第三方插件处理,每种类型的插件对应一个进程,仅当使用该插件时才创建;
4.渲染进程(Renderer进程):负责js执行,页面渲染,事件处理等功能,每个tab页面一个,互不影响;
(渲染进程主要包括 GUI线程、JS引擎线程、时间循环线程、定时器线程、http异步线程。)
①GUI渲染线程
浏览器拿到网页资源后的工作流程(GUI工作内容):
解析HTML字符串,结构化成DOM树(DOM Tree)——解析css,生成CSSOM(css规则树)——结合DOM树和CSSOM,生成Rendering Tree(渲染树)。
重绘(Repaint):只改变元素颜色、背景色之类,不影响布局,需要重新渲染的过程,叫做页面重绘;
回流(Reflow):改变页面布局、元素大小、隐藏等需要重新构建的过程,叫做页面回流。
回流之后会进行重绘,所以回流比重绘的成本高。
出现回流的场景:
1)页面渲染初始化。
2)添加、删除可见的DOM元素。
3)元素尺寸、位置变化。
4)窗口resize
②JS引擎线程
是渲染进程中的主线程,单线程运行,其他线程大部门都为了配合它工作。
另外,JS引擎线程与GUI渲染线程同时只能有一个在工作,JS会阻塞GUI渲染线程,GUI需要等到JS执行完毕才会继续渲染。
所以,js执行时间如果太长,就会导致页面卡顿。
③事件触发线程
控制事件循环,管理任务队列(有的也称为“事件队列”、“异步队列”);
将各种回调推入到任务队列中,包括用户交互回调(如click事件回调函数)、AJAX异步请求、定时器线程回调等。
④定时器线程
JS是单线程执行的,所以不能单独计时,浏览器只能另开辟一个线程用来处理定时器任务,到达定时器规定的时间时,任务会被推入到任务队列中,等待JS引擎线程进行处理。
⑤http异步线程
当JS引擎线程执行到异步请求时,会把异步请求事件添加到此进程当中,等待收到响应(即http状态发生变化时),将回调函数推入任务队列中,等待JS引擎线程来处理。
三、Eventloop事件轮询机制(这篇文章讲的非常通俗易懂:https://www.cnblogs.com/heshan1992/p/6650593.html)
JS单线程的本质是无法改变的,但JS的宿主环境(如浏览器,node)是多线程的,
为了解决JS单线程导致的阻塞问题,才有了异步的这种解决单线程阻塞问题的方案,
宿主环境会通过某种方式(比如:浏览器的事件轮询、node的事件驱动)使得JS具备了异步的特性。
第一种讲解:下图(截图自上面链接的文章中)很清楚的讲述了浏览器实现JS异步的具体解决方案——事件轮询机制:
第二种讲解:图片来自这篇文章:https://segmentfault.com/a/1190000013119813?utm_source=tag-newest
配合下图,同步操作运行在JS引擎线程上(主线程),形成一个执行栈,遇到异步操作,将异步事件分配给对应的线程去处理(如:定时器操作在定时器线程上,异步请求在http异步线程上),
事件循环线程会监听这些异步线程,每当这些异步操作有了结果的时候(如:定时器计时完成,http请求获取到响应),它们的回调函数变会被添加到异步队列的队尾,
当主线程中执行栈上的所有同步操作执行完的时候,异步队列中的异步回调函数会被推入执行栈进行执行,当主线程执行完,系统会再去异步队列中读取,循环往复,这期间,事件循环线程会一直监听着其他异步线程。
这便是事件轮询机制。