首先需要了解的是js语言的特点是单线程和解释性语言,
事件循环机制由三部分组成:调用栈、微任务队列、消息队列
1、event-loop开始的时候会从全局一行一行的执行 遇到函数调用会压入调用栈中 被压入的函数称之为帧 当函数返回后会从调用栈弹出,下面来看下面的代码:
function fn1() {
console.log(1)
}
function fn2() {
console.log(2)
fn1()
console.log(3)
}
fn2()
首先是fn2执行,fn2被压入调用栈中,输出结果为2,然后fn1被调用即fn1被压入到调用栈中,输出结果1;fn1执行完毕从调用栈中弹出,接下来输出3,3输出后fn2执行完毕,fn2也从调用栈中弹出,最终结果为2,1,3,如下图所示:
2、js的异步操作如 fetch setTimeout setInterval压入到调用栈时里面的消息会进入到消息队列中 消息队列会等到调用栈清空的时候立即执行,代码如下:
function func1() {
console.log(1);
}
function func2() {
setTimeout(() => {
console.log(2);
}, 0)
func1()
console.log(3);
}
func2()
首先func2执行,func2被压入到调用栈中,其中的setTimeout被压入到调用栈中,但其中的消息console.log(2)会进入到消息队列中,消息队列中的消息会等到调用栈中的内容执行完毕再执行;func1执行,func1被压入到调用栈中,输出结果1,func1执行完后被弹出,接下来输出3,之后func2被弹出调用栈,此时调用栈中的内容执行完毕,执行消息队列中的内容,输出2.所以最后的结果是:1 3 2 如下图所示:
3、promise async await的异步操作的时候会加入到微任务中 会在调用栈清空的时候立即执行 调用栈中加入的微任务会立即执行;微任务队列会比消息队列先执行。代码如下:
var p = new Promise(resolve => {
console.log(4);
resolve(5)
})
function func1() {
console.log(1);
}
function func2() {
setTimeout(() => {
console.log(2);
}, 0)
func1()
console.log(3);
p.then(resolve => {
console.log(resolve);
})
}
func2()
promise 属于微任务,当它压入到调用栈后会立即执行,输出4、resolve(5),fucn2执行,log(2)进入到消息队列中,然后func1执行,输出1,func1执行结束后弹出调用栈,然后输出3,然后p.then执行,被押入到微任务队列中,func2执行完毕被弹出调用栈,接下来执行微任务队列中的内容5,消息队列中的内容2;所以最终的执行顺序为4 1 3 5 2
执行结果如下图所示: