乐趣区

关于程序员:理解Javascript事件循环机制Event-Loop

js 是一个单线程

家喻户晓,古代的编程语言倒退很快,造成了多种语言,在这其中,js 是一个特例,它是一个单线程的语言,相比于 JAVA、PHP、Python,js 有它本人的独特,js 运行于浏览器中,在浏览器中创立 DOM、销毁 DOM,为了可能保障程序可能失常运行,在设计之初,就规定了 JS 只能是单线程,构想下:如果 JS 是一个多线程,在同一个时刻,有多个线程去操作 DOM。比方同时执行更新 DOM、销毁 DOM。浏览器会产生错乱,并不知道此时应该是如何解决,造成程序的谬误,所以 JS 是一个单线程。

了解堆 (stack) 和栈 (heap) 的概念

如果有同学晓得 JS 数据类型在内存中的存储形式,那么就应该晓得,JS 的根本数据类型 (string、number、boolean、null、undefined、symbol) 是存储在栈中,而援用类型数据 (Object、array、function) 是存储在堆中,理论这样并不精确,因为援用类型对应的 key 在栈中,对应的 value 是援用类型在栈中的指针,指针指向的是在堆中的地址,(如果你学习过计算机的基础知识的话)如果对于这个不理解的话,能够查看这篇文章: js 数据类型与内存存储 <br/>
与上述概念不同,明天所讲的堆和栈并不是这个概念(以下图来自 MDN)

当页面开始执行函数的时候,会把以后执行上下文 (content) 压入栈中,初始化的时候,会把 Global 压入最底下,而后把初始化函数在压入栈中,执行 init 办法会顺次的向外弹出 getList、init、Global,当浏览器调配的调用栈内存空间被占满时,就会引发常说的“堆栈溢出”谬误。

<script>
    function init () {}
    function getList () {}
    init ()

</script>
如果你能齐全了解以上的逻辑,那么以下的执行程序置信你也能得心应手
<script>
    setTimeout(() => {conosle.log('执行 setTimeout')
    }, 100)
    new Promise((reslove, reject) => {resolve('1')
    }).then(res => {console.log('2')
    })
    //‘1’//‘2’// 执行 setTimeout
</script>

了解工作队列概念

后面说过,JS 是一个单线程的,那么当执行工作的时候,就须要一个队列,排队执行,否则,工作凌乱,导致程序谬误,工作为同步工作和异步工作。异步工作在执行的时候不会阻塞主线程,会把工作放在一个队列外面,队列外面的工作分为宏工作 (macro-task) 和微工作(micro-task), 会优先清空微工作,在去清空宏工作,而后在去查看以后主线程,是否有新的工作产生,周而复始

常见的工作划分

宏工作 微工作
setTimeout promise(then、catch、finally)
setInterval process.nexttick
setImmediate MutationObserver
requestAnimationFrame

下图就是主线程和工作队列的示意图。

<br/>
(图来源于阮一峰博客)

残缺的事件循环

写在最初

我是crazyu,一位前端开发工程师。

  • 文中如有谬误,欢送在评论区斧正,如果这篇文章帮到了你,欢送点赞和关注😊
  • 本文首发于微信公众号:crazyu 前端,未经许可禁止转载
  • 加我微信号:crazyu_chang, 有任何问题能够随时与我沟通

本文由 mdnice 多平台公布

退出移动版