为什么不是setTimeout取消我的循环?

我想知道JavaScript语句(在Chrome的控制台中)可以在一毫秒内增加一个variables的次数,所以我很快就把这个代码片段直接写到了控制台中:

 var run = true, i = 0; setTimeout(function(){ run = false; }, 1); while(run){ i++; } 

问题是它永远运行。
为什么会发生这种情况,我该如何解决?

这回到了JavaScript 1的单线程本质。 会发生什么是这样的:

  1. 你的variables被分配。
  2. 你安排一个函数,设置run = false 。 计划在当前函数运行之后运行(或者其他任何当前活动的)。
  3. 你有无尽的循环,并留在当前的function。
  4. 在永无止境的循环之后( 永远不会 ), setTimeout()callback将被执行并且run=false

正如你所看到的,一个setTimeout()方法不会在这里工作。 你可以通过检查while条件中的时间来解决这个问题,但是这会篡改你的实际测量结果。

1至less为了更实际的目的,你可以把它看作是单线程的。 其实有一个所谓的“事件循环”。 在那个循环中,所有的函数都被排队,直到它们被执行。 如果你排队一个新的function,它被放在队列中的相应位置。 当前函数完成之后,引擎从队列中获取下一个函数(就引入的定时而言,例如setTimeout()并执行它。
因此,在每一个时间点,只有一个函数被执行,从而使得执行几乎是单线程的。 事件有一些例外情况,在下面的链接中讨论。


以供参考:

JavaScript是单线程的,所以,当你在循环中时,没有别的东西会被执行。

为了保持Chrome的真实速度,而不必经常检索计算速度的时间,你可以试试这个JS代码:

 var start = new Date().getTime() var i = 0 while(i<1000000) { i++ } var end = new Date().getTime() var delta = end-start var speed = i/delta console.log(speed + " loops per millisecond") 

Javascript是单线程的,意味着它一次只运行一条指令。

与许多其他语言和库一样,事件系统由事件循环来处理。 事件循环基本上是一个循环,在每次迭代时检查队列中的消息,并调度事件。

在JavaScript中(就像实现这种模式的语言一样),事件循环在堆栈为空时调用,也就是说,当所有函数都有返回时,换句话说,在程序代码结束时。

你的“真实”程序看起来像这样:

 var run = true, i = 0; setTimeout(function(){ run = false; }, 1); while(run){ i++; } while(true) { /* * check for new messages in the queue and dispatch * events if there are some */ processEvents(); } 

所以从时钟说超时的消息是从来没有处理。

有关事件循环的更多信息,请访问: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop


当然这有点复杂,请查看这些例子: JavaScript是否保证单线程? ( tl; dr:在一些浏览器引擎中,一些外部事件不依赖于事件循环,当它们发生时立即被触发,抢占当前任务,但是setTimeout并不是这样,它只是向队列中添加一条消息从不立即开火。)

While循环不访问setTimeout。 你有代码设置运行正确,然后它永远不会成为虚假的。

JavaScript具有单线程,并且在任何地方都有单线程。

我认为这个问题很好: JavaScript保证是单线程的?

当你的代码在循环其他ocde不执行和阻止。