返回

程序员面试高频题:宏任务和微任务的前世今生,快速通关秘笈!

前端

揭秘宏任务与微任务:面试官的最爱

在前端和计算机科学面试中,关于宏任务和微任务执行顺序的问题似乎永不过时。面试官可能会提问:“console.log() 会在哪些时机执行?setTimeout() 会在哪些时机执行?它们之间的执行顺序是什么?”

要巧妙地回答这个问题,我们需要深入了解宏任务和微任务的概念。

宏任务与微任务:大相径庭的兄弟

宏任务和微任务都是 JavaScript 中执行任务的机制。宏任务囊括脚本代码、setTimeout()、setInterval() 等函数,以及诸如 DOM 操作和 I/O 操作之类的操作。而微任务则包括 promise 的 resolve 和 reject 回调函数、MutationObserver 的回调函数,以及 DOM 事件处理函数等。

它们的差异主要在于执行时机和优先级。宏任务按照先入先出 (FIFO) 的顺序执行,而微任务遵循先进先出 (LIFO,后进先出) 的原则。此外,微任务优先于宏任务,这表明微任务将先于宏任务执行。

执行顺序:竞赛场上的博弈

为了直观地理解宏任务和微任务的执行顺序,我们可以将其比喻成一场竞速比赛,其中宏任务和微任务是两组参赛者,而执行顺序就是比赛规则。

宏任务组选手按照编号依次排队,微任务组选手亦是如此。比赛开始后,宏任务组的 1 号选手率先出发,微任务组的最后一位选手紧随其后。依此类推,宏任务组的 2 号选手与微任务组的倒数第二位选手同时出发。

由于微任务优先级更高,微任务组选手将率先冲向终点。当所有微任务组选手完成比赛后,宏任务组选手才能继续竞逐。

深入探索宏任务与微任务:解锁新境界

掌握宏任务和微任务的概念和区别后,我们还可以探究其底层原理和应用场景。

底层原理:JavaScript 引擎的幕后故事

宏任务和微任务的执行顺序由 JavaScript 引擎决定。该引擎拥有一个主线程和一个任务队列,其中宏任务和微任务排队等候执行。当主线程空闲时,它会从任务队列中取出一个任务执行。如果是宏任务,主线程将一直运行该宏任务,直至其完成。如果是微任务,主线程会先执行所有微任务,然后再处理宏任务。

应用场景:异步编程与并发编程

宏任务和微任务的概念在异步编程和并发编程中扮演着至关重要的角色。异步编程是指在不阻塞主线程的情况下执行任务,而并发编程则专注于同时执行多个任务。宏任务和微任务可帮助我们实现这两大编程范式。

例如,我们可以使用 setTimeout() 函数异步执行任务,避免阻塞主线程。同样,我们还可以借助 Promise 和 MutationObserver 实现并发编程,同步处理多个任务。

总结:宏任务与微任务,前端必备知识

宏任务和微任务是前端开发和计算机科学中的基石概念,透彻理解它们对于驾驭异步编程和并发编程至关重要。本文旨在阐明宏任务和微任务的概念、区别、执行顺序及其应用场景。通过深入了解这些机制,希望读者能够在项目中游刃有余地加以运用。

常见问题解答

  1. 宏任务和微任务是如何创建的?

    • 宏任务通常通过调用宏任务函数或执行 DOM 操作创建,而微任务则主要通过 Promise、MutationObserver 或 DOM 事件处理程序创建。
  2. 什么时候会使用宏任务?

    • 宏任务通常用于安排稍后执行的任务,例如通过 setTimeout() 安排的函数调用或 DOM 更新操作。
  3. 什么时候会使用微任务?

    • 微任务通常用于在当前上下文中立即执行回调函数,例如 Promise 的 resolve 或 reject 处理程序或 MutationObserver 回调。
  4. 除了 FIFO 和 LIFO,还有其他影响执行顺序的因素吗?

    • 通常情况下,FIFO 和 LIFO 规则适用于宏任务和微任务的执行,但某些特定场景可能存在例外,例如宏任务中的错误处理或微任务队列的嵌套。
  5. 如何使用宏任务和微任务进行有效的异步编程?

    • 有效利用宏任务和微任务的最佳实践包括避免在宏任务中执行耗时的操作,并利用微任务来处理快速且轻量级的操作。