javascript中的递归:不太明白

时间:2017-03-15 19:42:09

标签: javascript recursion

我正在练习使用递归,并且有一些我不太了解的东西。 例如,我编写了这个简单的倒计时函数,该函数应该等到第二个时间过去,直到倒数到下一秒。

我第一次写它是这样的:

function countdown(sec) {
  console.warn(sec);
  if(sec > 0) {
     sec--;
     setTimeout(countdown(sec), 1000);
  }
}

每个日志之间不会等待一秒钟。 这有效:

function countdown(sec){
   console.warn(sec);
   setTimeout(function() {
       sec--;
       if (sec > 0) {
          countdown(sec);
       }
   }, 1000);
};

我真的不明白第一种方法有什么问题。 我想这是setTimeout的东西,我不太明白,并且确定范围......?

提前感谢任何解释。

---编辑&工作,谢谢你们! ---

我不知道绑定被用作速记。

function countdown(sec) {
   console.warn(sec);
   if (sec > 0) {
       sec--;
       setTimeout(countdown.bind(null, sec), 1000);
   }
}

2 个答案:

答案 0 :(得分:1)

JosephNields对于为什么你的代码不起作用是正确的,但我还要强调递归通常不涉及改变状态值,即sec--

相反,只需将sec - 1作为countdown的下一个值。换句话说,设置 sec没有增加到较小的数字,只需用较小的数字递归

var countdown = function (sec) {
  console.log(sec)
  if (sec > 0)
    setTimeout(countdown, 1000, sec - 1)
}

countdown(10)

另外,知道计时器何时完成不是很好吗?此示例显示在您递归时传递另一个值。

var countdown = function (sec, done) {
  console.log(sec)
  if (sec > 0)
    setTimeout(countdown, 1000, sec - 1, done)
  else
    done()
}

countdown(5, function () {
  console.log('timer is all done!')
})

答案 1 :(得分:0)

setTimeout的第一个参数应该是一个函数。

当您致电setTimeout(countdown(sec),1000)时,它会被评估为setTimeout(undefined, 1000),因为countdown(sec)不会返回值。

您的第二种方法有效,但作为简写,您也可以这样做:setTimout(coundown.bind(null, sec), 1000)。这会创建一个在调用时执行countdown(sec)的函数,它基本上等同于以下内容:

setTimeout(
    function() {
        countdown(sec);
    }, 
    1000
);

更多信息: Use of the JavaScript 'bind' method