从浏览器进程到JavaScript单线程:最全面的JavaScript运行机制解析
2023-12-01 08:29:55
春天已至,三月的脚步声渐进,迎来早读文章分享。由@撒网要见鱼授权分享,一起开启今天的阅读之旅。
最近发现不少介绍JavaScript单线程运行的文章,很多只关注某个方面,说法也不统一,容易混淆。
为了理清这一知识点,我们将结合已有的认知和网上的参考资料,全面地解析JavaScript的运行机制。
浏览器多进程
浏览器的工作原理基于多进程架构,每个进程独立于其他进程运行,拥有自己的内存空间和资源,这样可以提高浏览器稳定性。
一个浏览器可能有多个进程:
- 主进程:负责管理浏览器窗口、选项卡和插件。
- 渲染进程:负责将HTML、CSS和JavaScript代码渲染为页面,每个选项卡对应一个渲染进程。
- GPU进程:负责处理图形和视频的渲染,在涉及视频或3D效果的页面中更为重要。
- 插件进程:负责处理浏览器插件,如Adobe Flash Player或Java插件。
JavaScript单线程
JavaScript在浏览器中是单线程运行的,也就是说,同一时间只有一个线程在执行代码。这种单线程模式有以下几个原因:
- 为了保证JavaScript执行的一致性,避免多线程并发执行造成的数据竞争和不确定性。
- JavaScript通常用于处理用户交互、动画和网络请求,这些任务往往是顺序执行的,不需要多线程。
- 为了降低浏览器资源消耗和复杂性。
EventLoop
JavaScript单线程由EventLoop驱动,EventLoop是一个事件循环机制,不断轮询检查是否有事件发生,并执行对应的回调函数。
EventLoop由以下步骤组成:
- 检查任务队列,如果有任务,则执行。
- 检查微任务队列,如果有微任务,则执行。
- 如果没有任务或微任务,则阻塞等待,直到有事件发生。
EventLoop不断重复这三个步骤,直到所有任务和微任务都执行完毕。
任务队列
任务队列是存放宏任务的队列,宏任务是常规的JavaScript函数,当函数被调用时,它会被放入任务队列中。
EventLoop不断从任务队列中取出任务并执行,直到队列为空。
微任务队列
微任务队列是存放微任务的队列,微任务是Promise的回调函数、MutationObserver的回调函数和某些浏览器的requestAnimationFrame回调函数。
微任务队列的优先级高于任务队列,当微任务队列中有微任务时,EventLoop会先执行微任务,然后再去执行任务队列中的任务。
宏任务与微任务
宏任务与微任务的主要区别在于执行时机。
宏任务在任务队列中执行,通常在EventLoop的下一次循环中执行。而微任务在微任务队列中执行,通常在当前EventLoop循环中执行,在所有宏任务之前执行。
总结
JavaScript在浏览器中是单线程运行的,由EventLoop驱动,EventLoop不断轮询检查是否有事件发生,并执行对应的回调函数。
EventLoop由任务队列和微任务队列组成,任务队列存放宏任务,微任务队列存放微任务。
微任务队列的优先级高于任务队列,当微任务队列中有微任务时,EventLoop会先执行微任务,然后再去执行任务队列中的任务。
通过对JavaScript运行机制的深入理解,我们可以更好地编写出高效、可靠的JavaScript代码。