在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 应用程序或服务器中看到的所有 异步 行为都是由于形成 事件循环 .
的其他部分造成的
这也是它的简化图。事件队列有更多的划分,但这超出了这个问题的范围。
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 应用程序或服务器中看到的所有 异步 行为都是由于形成 事件循环 .
的其他部分造成的这也是它的简化图。事件队列有更多的划分,但这超出了这个问题的范围。