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

递归结合setTimeout异常:为何数字打印无法正常终止?

递归定时器函数无限打印问题排查

我需要编写一个递归函数,实现每隔1秒打印1到10的数字。尽管已编写递归退出条件,但当前函数打印数字从1开始,在达到10后仍继续无限打印,请问问题出在哪里?

原代码

function printNumbers2(from, to) {
  let number = from;

  if (number == to) {
    return number;
  } else {
    return setTimeout(() => {
      console.log(number);
      number++;
      printNumbers2(number);
    }, 1000);
  }
}

console.log(printNumbers2(1, 10));

运行结果

Timeout {
  _idleTimeout: 1000,
  _idlePrev: [TimersList],
  _idleNext: [TimersList],
  _idleStart: 15,
  _onTimeout: [Function (anonymous)],
  _timerArgs: undefined,
  _repeat: null,
  _destroyed: false,
  [Symbol(refed)]: true,
  [Symbol(kHasPrimitive)]: false,
  [Symbol(asyncId)]: 2,
  [Symbol(triggerId)]: 1
}
1
2
3
4
5
6
7
8
9
10
11
12
13
...

问题分析

  1. 递归调用未传递to参数:函数定义需要from和to两个参数,但递归时只传了number,导致后续调用中to的值为undefined。此时退出条件number == to永远不成立(数字与undefined无法相等),递归无法终止,会无限执行。
  2. 退出逻辑遗漏目标值打印:原代码中number == to时直接返回,这会导致目标值10无法被打印——因为只有else分支才会执行打印和递归操作。实际运行中能打印10,是因为当number为9时进入else,打印9后number变为10,接着调用printNumbers2(10),此时to是undefined,所以又进入else分支打印了10,随后number变为11,继续无限递归。

修正后的代码

function printNumbers2(from, to) {
  let number = from;

  // 先打印当前数字,确保目标值10也能被输出
  console.log(number);

  // 严格判断当前数字是否等于目标值,满足则终止递归
  if (number === to) {
    return;
  }

  // 1秒后递归调用,必须传递下一个数字和目标值to
  setTimeout(() => {
    printNumbers2(number + 1, to);
  }, 1000);
}

printNumbers2(1, 10);

修正说明

  • 递归调用时始终传递to参数,保证每次调用都能正确判断终止条件;
  • 调整执行顺序,先打印当前数字再判断终止,确保目标值10被输出;
  • 使用===严格相等运算符,避免类型隐式转换带来的判断误差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:53:14