You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在循环条件中使用Date.now()会造成无限循环?含setTimeout疑问

JavaScript循环与事件循环的两个问题解答

一、为什么固定a的while循环看起来像无限循环?

你的第一个示例代码:

let a = Date.now() + 5000;
while(Date.now() < a) {
    console.log(1);
}

这个循环不是真的无限循环,只是执行时会疯狂输出1,加上浏览器主线程被完全占用导致UI卡死,让你误以为它永远停不下来:

  • a在代码初始化时就被赋值为「当前时间+5000毫秒」,是一个固定值
  • 每次循环都会调用Date.now()获取最新的当前时间,当当前时间超过a时,循环就会自动终止
  • 之所以观感像“无限”,是因为console.log(1)的执行频率极高,5秒内会输出几十万次,期间浏览器无法响应任何交互,容易让人产生循环永远不会结束的错觉。

二、为什么长时间while循环后,setTimeout的回调仍能触发?

你的第二个示例代码:

setTimeout(() => {
    alert(2);
}, 2000);
let a = Date.now() + 5000;
while( Date.now() < a ) {
    console.log(1)
}

这要从JavaScript的单线程事件循环机制说起:

  • JavaScript是单线程语言,所有同步任务都会在主线程的执行栈中依次执行,期间不会被打断
  • setTimeout属于「宏任务」,它的回调函数不会立刻执行,而是会被加入到任务队列中,等待主线程的所有同步任务执行完毕后,才会被取出执行
  • 你的代码中,先注册了setTimeout回调,随后开始执行5秒的while循环——这是同步任务,会占满主线程,任务队列里的setTimeout回调只能一直等待
  • 当5秒后while循环结束,主线程空闲下来,才会去处理任务队列里的回调,此时才会弹出alert(2)
  • 你误以为“循环没结束setTimeout就触发”,其实是循环结束后才执行的,只是循环的5秒比setTimeout设置的2秒长,等循环结束时,回调已经在队列里等了3秒,所以会立刻执行。

内容的提问来源于stack exchange,提问作者JAck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:16:14