想必面试题刷的多的同窗对下面这道题目不陌生,可以当即回答出输出10个10,但是你真的懂为何吗?为何是输出10?为何是输出10个10?这两个问题在我脑边萦绕。嗯,我得说服本身。html
for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i) }, 0) }
JavaScript 是单线程。(ok,我又问本身它为何是单线程 ==》做为浏览器语言,JS的用途是与用户交互以及操做DOM,若是是多线程会引起不少问题,浏览器没法判断以哪一个线程为标准,所以它只能是单线程)
任务分为「同步任务」与「异步任务」。同步任务都好理解,一个执行完执行下一个。异步任务稍许复杂。
异步任务运行机制:java
其实屡清楚很好理解,以上运行机制又称为 Event Loop
(事件循环)
咱们回到这道面试题, 一块儿来理解下:git
for 循环是同步任务,setTimeout 是异步任务 首先 for 循环在主线程上执行,setTimeout 进入任务队列 同步任务执行完,i = 10,此时 setTimeout 被唤醒进入执行栈执行 所以输出的值为10 但是为何会输出10个10呢?到如今我仍是没有彻底说服本身。
咱们对代码稍做修改,github
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异步及浏览器更新渲染时机异步