【问题标题】:Why doesn't += work in recursion?为什么 += 在递归中不起作用?
【发布时间】:2017-01-20 20:37:10
【问题描述】:

我注意到如果我在递归中使用+=,它会无限期地运行,因为在终止语句中使用的变量的值不会增加。我不知道为什么,我已经在论坛上寻找答案但没有看到答案。我试图弄清楚我是否做错了什么,如果没有,我正在寻找关于它为什么不起作用的具体答案。

//this works fine
function recure(n = 0) {
    if (n > 10) {
        console.log('The End');
        return '';
    }
    console.log(n);
    setTimeout(function () {
        recure(n + 1)
    }, 1000);
}
recure();

//this also works fine, note it's working with n+=1
function loop(amount = 10, n = 1) {
    for (let i = 0; i < amount; i++) {
        console.log(n);
        n += 1;
    }
}

//This doesn't work and is the reason for the post, why?
function recure(n = 0) {
    if (n > 10) {
        console.log('The End');
        return '';  
    }
    console.log(n);
    n += 1;
    setTimeout(function () {
        recure()
    }, 1000);
}
recure();    //it indefinitely logs 0

【问题讨论】:

  • 每次调用都会初始化一个本地的n,其值为0。将n 传递给递归调用。 recurse(n)
  • recure(n=0)....
  • 你没有传递n的更新值所以它默认为0?
  • 将 setTimeout 更改为 setTimeout(function(){recure(n)},1000);

标签: javascript recursion


【解决方案1】:

n 对于函数的特定调用是本地的。由于您在没有参数的情况下调用您的函数,它会将 new n 绑定到 0

function test(n=0){
  return n;
}

test();  //==> 0
test(2); //==> 2

递归并没有真正被特殊对待,因此如果您假设 n 在对 recure 的调用之间保持不变,这也应该发生:

function other(n=0) {
  return n;
}
function test(n=0) {
  n++;
  return other();
}

test(0); // ==> 1

然而这是荒谬的,因为n 是本地的,因此即使函数相同,每次调用都会赢得n

还要注意第三个例子不是递归,因为调用堆栈被重置。

您调用recure 的匿名函数在其词法范围内有n,因此您可以使用n+1 调用它,因此新的recure 将得到一个n,它比调用的高一个thunk 源自。

【讨论】:

    【解决方案2】:

    在 JavaScript 中,变量的范围是由函数定义的。因此,当您调用函数 recur() 时,会在每个范围内创建一个新范围,并使用新的“N”。

    让我们试着理解你在这里做什么:

    1. You called recure(). 
     // No argument hence "N" is undefined therefore N is assigned 0.
    
    2. You incremented value of "N"
     // New value of "N" = 1
    
    3. You recursively called recure()
     // Again no argument hence "N" is 0
     // Since, recure() is called again new scope is created
     // This "N" is different from the "N" used is step 1
    
    4. Bad recursion --> #Fail.
    

    【讨论】:

      【解决方案3】:

      //this works fine
      function recure(n = 0){
          if (n > 10) {
              console.log('The End');
              return '';
          }
          console.log(n);
          setTimeout(function() {
              recure(n + 1)
          }, 1000);
      }
      recure();
      
      //this also works fine, note it's working with n+=1
      function loop(amount = 10, n = 1) {
          for (let i = 0; i < amount; i++) {
              console.log(n);
              n += 1;
          }
      }
      
      //This doesn't work and is the reason for the post, why?
      function recure(n = 0) {
          if (n > 10) {
              console.log('The End');
              return '';  
          }
          console.log(n);
          n += 1;
        setTimeout(function(){recure(n)},1000);
      }
      recure();    //it indefinitely logs 0
      &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

      【讨论】:

        【解决方案4】:

        这应该可以工作

        function recure(n=0){
            if(n>10){
                console.log("The End");
                return "";  
              }
            console.log(n);
            n+=1;
            setTimeout(function(){recure(n)},1000);
          }
        recure();
        

        在递归的每个阶段,特定的闭包都应该知道之前的递归状态。 我们通过 'n' 来了解递归的状态。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-02
          • 1970-01-01
          • 2017-04-28
          • 2016-09-07
          • 2021-10-28
          • 2023-02-07
          相关资源
          最近更新 更多