在javascript中,下面的代码为什么不退出循环?

In javascript, why doesn't the below code exit the loop?

let a = true;
setTimeout(() => {a = false}, 1000)
while(a){console.log(a)}

因为JS是单线程的,在线程不忙的时候setTimeout会在1000ms后运行。由于此 while 循环阻塞线程,setTimeout 的回调没有时间到 运行,因此 a 永远保持 true

您可以找到有关此主题的更多详细信息 here

setTimeout 是异步函数,只有在javascript 调用栈为空时才会执行提供的回调。因为我们有“while(true)”条件,它总是会执行一些东西 => 调用堆栈永远不会为空 => setTimeout 回调永远不会被执行。 有关详细信息,请阅读 JavaScript 事件循环 https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop

让我们一步一步地看这个(如果这是在浏览器中执行的):-

let a = true;
setTimeout(() => {a = false}, 1000)
while(a){console.log(a)}
  • let a = true; :您将新变量 a 初始化为 true;

  • setTimeout(() => {a = false}, 1000) : 你已经告诉浏览器的 setTimeout Web API 执行一个 callback (() => {a = false}) 其中我们在 1[=74 的 minimum 之后将 a 设置为 false =] 第二。 最小值 因为 回调 不会执行,除非 JavaScript 执行堆栈(这是你所有的 JS 代码实际执行 同步 ) 是空的。此 回调1s 后被放入 事件队列 并且 出队 仅当 JavaScript 执行堆栈 为空时从那里开始。

  • while(a){console.log(a)} :这将执行 同步 并阻塞 主线程 (其中执行堆栈是)因为 a 总是正确的。我们的 主线程 被阻塞意味着完成这个操作太昂贵了(这是有道理的,因为它是无限日志记录)所以 JavaScript 执行堆栈 对于 事件队列 中可用的任何 回调 永远不可能是免费的。这意味着 () => {a = false} 即使在 事件队列 中可用,也永远不会有机会在我们的 dequeued 和 运行 中JavaScript执行栈.

浏览器的Web API,这个JavaScript执行栈事件queue 共同构成了浏览器的 事件循环

JavaScript单线程(还记得主线程吗?)同步 语。您在 Web 应用程序或服务器中看到的所有 异步 行为都是由于形成 事件循环 .

的其他部分造成的

这也是它的简化图。事件队列有更多的划分,但这超出了这个问题的范围。