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

异步行为疑问:递归setTimeout未执行完毕就执行后续代码的原因

为什么递归setTimeout完成前后续代码就执行了?

我来帮你拆解这个问题的核心——这其实是JavaScript**事件循环(Event Loop)**在搞事情!先看你的代码:

console.clear(); 
var a = 1; 
function logA() { 
  if (a<11) { 
    console.log(a); 
    a++; 
    setTimeout(logA, 100); 
  } else { 
    return; 
  } 
} 
logA(); 
console.log("after set timeout"); 

调用栈和事件循环的完整流程

我一步步给你捋清楚调用栈里发生的每一件事:

  • 首先,所有同步代码按顺序执行:
    1. 执行console.clear(),完成后从调用栈弹出。
    2. 声明并赋值a=1,完成后弹出。
    3. 声明logA函数,只是定义不执行,跳过。
    4. 调用logA(),把logA压入调用栈:
      • 此时a=1<11,执行console.log(1),然后a变成2。
      • 调用setTimeout(logA, 100):这里注意!setTimeout不会立刻执行回调函数,它会把logA这个回调放到宏任务队列里排队,然后setTimeout本身执行完毕,从调用栈弹出。
      • 第一次logA函数执行完毕,从调用栈弹出。
  • 现在调用栈空了吗?不,还有最后一行同步代码console.log("after set timeout")!这行是同步任务,直接压入调用栈执行,所以你会先看到控制台打印出这句话。
  • 等100毫秒后,浏览器会检查宏任务队列,发现里面有logA回调,就把它压入调用栈执行:
    • 重复之前的逻辑:打印当前a的值,a自增,再把下一个logA回调放进宏任务队列,直到a>=11时,logA执行return,不再添加新的宏任务,整个循环结束。

简单来说:setTimeout是异步任务,它的回调不会阻塞同步代码的执行,同步代码会优先全部跑完,异步任务才会在调用栈空闲时依次执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:41:30