堆与栈
我们的数据会在栈(stack)中执行,但是还有一些数据会存在堆(heap)
stack: 就是主线程和任务被执行的地方
heap: 就是我们一些费结构化数据,例如变量…
栈:一层一层往里放东西,出的时候先把最外面的拿掉,在拿里面的
队列:一个一个放,出的时候先拿第一个,在拿第二个
宏任务 & 微任务
宏任务(MacroTask)&&宏任务队列
宏任务总是在下一个eventLoop执行,在微任务之后,在执行宏任务中如果添加了新的微任务,会把新的微任务添加到微任务的队列中。
宏任务队列每次都会取出1条任务放到执行栈中。
- setTimeout
- setInterval
- setImmediate(IE专用,比setTimeout慢一点)
- MessageChannel
微任务(MicroTask)&&微任务队列
在微任务执行中,出现新的微任务会把新的微任务放在当前队列的末尾。
微任务在本轮的eventLoop中执行完后,马上把执行栈中的任务都执行完。 - promise.then
- MutationObserve(H5中的方法,兼容性差)
任务队列
- 所有同步代码都在主线程上执行,形成一个执行栈
- 浏览器机制先执行栈中的,然后微任务和宏任务的回调会分开存放,栈中执行完毕会把微任务队列中的所有微任务都执行完毕,微任务执行完,会取出宏任务队列中的第一个任务执行,执行完然后清空微任务队列
- 重复第二条依次循环
实例辅助
Promise.resolve().then(function () {
console.log('then1');
setTimeout(() => {
console.log('timer1')
}, 0);
})
setTimeout(() => {
console.log('timer2')
Promise.resolve().then(function () {
console.log('then2')
})
}, 0);
// then1 timer2 then2 timer1
上面代码流程:
- 代码从上到下执行,先把微任务和宏任务分别丢到对应的队列中
- 执行第一个promise。输出 then1 ,然后发现有一个宏任务,丢到宏任务队列中
- 执行完第一个微任务,到时间从宏任务队列中取出第一个宏任务执行,输出timer2 ,然后有一个微任务promise,把新的微任务放入到微任务队列中,清空执行栈,然后去执行新的微任务,输出 then2
- 最后,在把宏任务队列中的输出 timer1