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

异步JavaScript中let声明变量时do/while与for循环输出不一致原因探究

为什么do/while与for循环搭配setTimeout会输出不同结果?

先看这段do/while循环的代码:

function logNum() {
  let counter = 0;

  do {
    counter += 1;
    setTimeout(() => console.log(counter), counter * 1000);
  } while(counter <= 10);
}

logNum();

这段代码运行后会连续10次输出11,但预期效果是依次输出1到10。

再看for循环的实现版本:

function logNum() {
  for (let counter = 1; counter <= 10; counter += 1) {
    setTimeout(() => console.log(counter), counter * 1000);
  }
}

logNum();

这个版本却能按预期依次输出1到10,差异的核心原因如下:

核心原因:let在循环中的作用域绑定差异

  • do/while循环场景:counter是在循环外部声明的,整个循环周期内只有这一个counter变量。setTimeout的回调是异步执行的,等所有回调触发时,循环早已执行完毕,此时counter的值已经变为11,所以所有回调都会输出这个最终值。
  • for循环场景:用let声明的循环变量,会在每一轮迭代时创建一个全新的变量绑定。也就是说,每一次循环的counter都是独立的,setTimeout的回调会捕获当前迭代对应的那个counter值,因此最终能依次输出1到10。

do/while循环的修正方案

要让do/while循环达到预期效果,需要在每次迭代中创建独立变量保存当前counter的值,避免回调捕获到循环结束后的最终值:

function logNum() {
  let counter = 0;

  do {
    let num;
    counter += 1;

    num = counter;
    setTimeout(() => console.log(num), num * 1000);
  } while(counter < 10);
}

logNum();

这里每轮迭代都会声明新的num变量,保存当前counter的快照值,回调函数捕获的是这个独立的num,因此能正确输出对应数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:10:18