资讯专栏INFORMATION COLUMN

一道面试题引发的思考 --- Event Loop

betacat / 3167人阅读

摘要:想必面试题刷的多的同学对下面这道题目不陌生,能够立即回答出输出个,可是你真的懂为什么吗为什么是输出为什么是输出个这两个问题在我脑边萦绕。同步任务都好理解,一个执行完执行下一个。本文只是我对这道面试题的一点思考,有误的地方望批评指正。

想必面试题刷的多的同学对下面这道题目不陌生,能够立即回答出输出10个10,可是你真的懂为什么吗?为什么是输出10?为什么是输出10个10?这两个问题在我脑边萦绕。嗯,我得说服自己。

for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i)
  }, 0)
}

JavaScript 是单线程。(ok,我又问自己它为什么是单线程 ==》作为浏览器语言,JS的用途是与用户交互以及操作DOM,如果是多线程会引发很多问题,浏览器无法判断以哪个线程为标准,因此它只能是单线程)
任务分为「同步任务」与「异步任务」。同步任务都好理解,一个执行完执行下一个。异步任务稍许复杂。
异步任务运行机制:

同步任务在「主线程」上执行,形成一个「执行栈」(execution context stack)

主线程之外,还有一个「任务队列」(task queue),异步任务有了运行结果,就在任务队列里放置一个事件

执行栈中同步任务执行完,就会去读取任务队列的事件,异步任务事件结束等待状态,进入执行栈执行

主线程重复前面三步

其实屡清楚很好理解,以上运行机制又称为 Event Loop(事件循环)
我们回到这道面试题, 一起来理解下:

for 循环是同步任务,setTimeout 是异步任务
首先 for 循环在主线程上执行,setTimeout 进入任务队列
同步任务执行完,i = 10,此时 setTimeout 被唤醒进入执行栈执行
因此输出的值为10
可是为什么会输出10个10呢?到现在我还是没有完全说服自己。

我们对代码稍作修改,

for (var i = 0; i < 10; i++) {
  console.log(i)
  var p = setTimeout(() => {
    console.log(i)
  }, 0)
  console.log(p)
}

输出结果

0
Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: TimersList, _idleStart: 1893, …}
1
Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 3739, …}
2
Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 4924, …}
......
9
Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 11733, …}
10
10
...
10

看到这个结果大家是否有些清楚了呢,我们重新梳理下原先的面试题

首先 for 循环在主线程上执行,setTimeout 内部的回调函数进入任务队列
for 循环里,i 每次执行一次,异步队列里放置一个 setTimeout 回调
同步任务执行完,i = 10, 此时异步队列里放置了10个回调事件
setTimeout 被唤醒进入执行栈执行
因此输出了10个10

当然了, Event Loop 的知识不止这点,涉及到的东西也很多。本文只是我对这道面试题的一点思考,有误的地方望批评指正。

以下几篇是我收藏的好文,供大家学习参考~
JavaScript 运行机制详解:再谈Event Loop
这一次,彻底弄懂 JavaScript 执行机制
从event loop规范探究javaScript异步及浏览器更新渲染时机

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100294.html

相关文章

  • 面试不倒翁:一道事件循环引发血案

    摘要:通过查看的文档可以发现整个分为个阶段定时器相关任务,中我们关注的是它会执行和中到期的回调执行某些系统操作的回调内部使用执行,一定条件下会在这个阶段阻塞住执行的回调如果或者关闭了,就会在这个阶段触发事件,执行事件的回调的代码在文件中。 showImg(https://segmentfault.com/img/bVbd7B7?w=1227&h=644); 这次我们就不要那么多前戏,直奔主题...

    ispring 评论0 收藏0
  • 一道前端面试引发思考

    摘要:直接开始题目是厉害了说句实话开发中谁写成这样保证会被打死。不过面试就是面试,有面试官的考量点。官方是这么说的。结果完美,不过小姐姐的意思是数组的方法会自动触发数组的。 直接开始题目是 if(a==1 && a==2 && a==3){ alert(厉害了) } 说句实话开发中谁写成这样保证会被打死。 不过面试就是面试,有面试官的考量点。 我理解的点有两个 1、隐式类型转换 先说...

    gaomysion 评论0 收藏0
  • 「今日头条」前端面试和思路解析

    摘要:一篇文章和一道面试题最近,有篇名为张图帮你一步步看清和的执行顺序的文章引起了我的关注。作者用一道年今日头条的前端面试题为引子,分步讲解了最终结果的执行原因。从字面意思理解,让我们等等。当前的最新版本,在这里的执行顺序上,的确存在有问题。 一篇文章和一道面试题 最近,有篇名为 《8张图帮你一步步看清 async/await 和 promise 的执行顺序》 的文章引起了我的关注。 作者用...

    宠来也 评论0 收藏0
  • 一道简单面试引发思考

    摘要:另一个问题,就是我下面要提及的作用域问题,我当时思考的时间太久了这是回忆中的面试题实际略有差异,不纠结了说一下脚本的运行结果引用错误中给出的错误提示。 版权声明:此文首发于我的简书账号人生还有多少个二十年,转载请注明出处。 此处有几百字唠叨:   当天,我早早起床,跨越上百公里,高德导航,路人指点,跌跌撞撞到达招聘会现场,当时已是中午十二点半,吃了午餐(半瓶白开水),开始准备投递...

    wpw 评论0 收藏0
  • 链式调用与事件循环--一道JavaScript面试思考

    摘要:最后画几张粗糙的图,简单描述一下这个执行的过程因为是链式调用,所以在链上的都会入栈然后执行,额,执行栈少画了和。。。 前言:昨天在群里讨(jin)论(chui)技(niu)术(pi),有位老铁发了一道他面的某公司面试题,顺手保存了。今早花了一点时间把这题做了出来,发现挺有意思的,决定在今天认真工(hua)作(shui)前,与大家分享我的解题方案和思考过程。 题目如下(可以自己先思考一会...

    wow_worktile 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<