事件循环
在了解什么是事件循环之前我们需要知道JavaScript的函数调用机制。
栈
函数调用形成了一个由若干帧组成的栈。—引用于MDN对于事件循环的讲解
function a(num) {
let m = 10;
return m + num + 1;
}
function b(x) {
let y = 3;
return a(x * y);
}
console.log(b(7)); // 返回 32
当调用 b时,第一个帧被创建并压入栈中,帧中包含了 b的参数和局部变量。 当 b调用 a时,第二个帧被创建并被压入栈中,放在第一个帧之上,帧中包含 a的参数和局部变量。当 a执行完毕然后返回时,第二个帧就被弹出栈(剩下 b函数的调用帧 )。当 b也执行完毕然后返回时,第一个帧也被弹出,栈就被清空了。—引用于MDN对于事件循环的讲解。先进后出。
最后栈清空,执行队列清空。
同步执行下是如此进行,但是在异步执行下就会出现不同的情况。
什么是事件循环
事件循环就是在执行队列时它会循环的去读取栈堆当中的需要处理的事件直到不再有需要处理的事件为止。同时它会优先读取执行栈中的同步任务,异步任务在其之后。
异步定时器的不准时
为什么在我们设置的定时器中,有些不会准时执行。
比如:
setTimeout(function(){console.log(1);}, 0);
console.log(2);
首先输出的是 2 ,其后才是 0;
因为在事件循环中,当定时器设置的延时事件与某一同步执行的事件相遇,会先执行同步事件,同时定时器的回调还在队列中排队,在前面的出栈后,才会入队执行。所以在有时候我们设置延时回调时有些执行事件并不准确就是因为在其之前还有事件任务,导致后续进入队列的函数在排队当中,因此延时回调会比预计延时时间长。
微任务到宏任务:一次明白event loop