JavaScript 的执行机制是基于单线程的事件循环模型。这意味着 JavaScript 代码会按照顺序一行一行地执行,同时只能执行一个任务。让我们更详细地了解 JavaScript 的执行机制:
-
调用栈(Call Stack):
JavaScript 使用调用栈来追踪代码的执行顺序。每当调用一个函数,该函数会被推入调用栈中,执行完成后从栈中弹出。这意味着 JavaScript 是通过函数调用(包括自身递归调用)来实现代码的执行。 -
事件循环(Event Loop):
JavaScript 的事件循环负责管理异步任务的执行。当遇到异步任务(如定时器、网络请求等),它们会被放入任务队列(Task Queue)中等待执行。事件循环会不断地从任务队列中取出任务,放入调用栈中执行。 -
任务队列(Task Queue):
任务队列用于存储异步任务。JavaScript 运行时环境提供了不同类型的任务队列,如宏任务队列(Macrotask Queue) 和微任务队列(Microtask Queue)。-
宏任务队列:包含一些异步操作,通常是由浏览器提供的 API 发起的,如定时器回调(setTimeout、setInterval)、DOM 事件回调等。
-
微任务队列:用于存储具有高优先级的任务,如 Promise 的回调、
MutationObserver
的回调等。
-
-
执行过程:
当 JavaScript 的调用栈为空时,事件循环会从任务队列中选取一个任务,将其放入调用栈中执行。这个过程会持续进行,直到调用栈继续为空。执行过程可以总结为以下步骤:- 检查调用栈是否为空。
- 如果调用栈为空,则从宏任务队列中选择一个任务并将其放入调用栈中执行。
- 如果宏任务执行过程中产生了微任务(例如 Promise 的回调),则将这些微任务放入微任务队列中。
- 当宏任务执行完成后,检查微任务队列是否为空。
- 如果微任务队列非空,则依次将微任务放入调用栈中执行,直到微任务队列为空。
- 回到第一步,继续检查调用栈是否为空,并重复上述步骤。
需要注意的是,JavaScript 中的同步代码(如普通函数调用)会直接在调用栈中执行,而异步代码(如定时器回调)会进入任务队列等待执行。这样避免了长时间的阻塞,同时支持并发执行多个异步任务。