前言
先上一段代码,可以根据自己之前对 JS 执行机制的理解,进行分析
console.log(‘script start’);
setTimeout(function() {
console.log(‘setTimeout’);
}, 0);
Promise.resolve().then(function() {
console.log(‘promise1’);
}).then(function() {
console.log(‘promise2’);
});
console.log(‘script end’);
答案:script startscript endpromise1promise2setTimeout
如果自己的答案和上面的答案有出入,请继续阅读
基本概念的阐述
调用堆栈
JavaScript 有一个单独的调用堆栈,负责执行 JS 代码,当即将执行一个函数时,此函数就会被添加到调用堆栈中,当此函数执行完,则会出栈。
事件表
每次调用 setTimeout 函数或执行异步操作时,都会将其添加到事件表中,事件表负责记录每个事件完成后执行的回调函数,并监听事件,事件完成后会把事件的回调函数发送到事件队列。
事件队列
事件队列接收来自事件表的回调函数,并根据顺序执行。事件队列中存储两种任务:微任务和宏任务
在当前的微任务没有执行完成时,是不会执行下一个宏任务的。这里有两种说法,一种说法把刚开始执行的整体 JS 代码认为是一个宏任务,先执行整体 JS 代码这一个宏任务,执行完成后,再执行微任务列表中的所有微任务,所以认为先执一个行宏任务再执行所有微任务
另外一种说法没有把刚开始的 JS 代码当做宏任务,所以起始执行的是微任务,所有微任务执行完再执行宏任务,认为先执行微任务再执行宏任务 其实两种说法的核心是一样的,都是执行一个宏任务 执行所有微任务事件循环
事件循环就是一个持续运行的进程,用于检查调用堆栈是否为空。将我们上面所述连接起来,并循环执行。
JS 执行机制
console.log(‘script start’);
setTimeout(function() {
console.log(‘setTimeout’);
}, 0);
Promise.resolve().then(function() {
console.log(‘promise1’);
}).then(function() {
console.log(‘promise2’);
});
console.log(‘script end’);
再次分析此段代码最初始状态:JS 调用栈为空,任务队列中宏任务队列有 script 代码块就绪第一步:检查调用栈为空,将宏任务 script 入栈,开始向下执行第二步:当遇到异步操作时,执行异步,并将异步事件与其回调函数注册到事件列表,同步代码继续执行第三步:当事件表监听到异步事件已经完成,将其事件的回调函数入队(任务队列)第四步:检查到调用栈为空,先将微任务依次入栈(调用堆栈)执行,微任务列表为空时,将宏任务入栈(调用堆栈)执行更多关于 JS 执行机制的理解请点击下面链接,有动画效果有助于理解 特别推荐 Tasks, microtasks, queues and schedules