我不懂JavaScript中的递归

时间:2017-01-31 21:31:49

标签: javascript

我不明白这一点!

function rec(arg){
    console.log(arg);
    if(arg == 3)
        return arg;
    else 
        rec(arg + 1);
}

var i = rec(0);
console.log(i);
//0
//1
//2
//3
//undefined

为什么函数'arg'里面有一个值但是当它返回它时('arg == 3')它给我'未定义'?

这是另一个

function power(base, exponent) {
 console.log(exponent);
 if (exponent == 0)
   return 1;
 else
   return base * power(base, exponent - 1);
}

console.log(power(2, 3));
//3
//2
//1
//0
//8

为什么当函数内的'exponent'为'0'时返回'8'并且它应该返回'1'!

我现在明白,我不了解JS是如何运作的。

3 个答案:

答案 0 :(得分:3)

在你的第一个例子中,你应该写一行

  

if(arg == 3)返回arg;否则rec(arg + 1);

这个

  

如果(arg == 3)返回arg;否则返回 rec(arg + 1);

在第二个示例中,您应该更改行

  

return base * power(base,exponent - 1);

  

返回Math.pow(base,exponent);

(实际上,您应该通过调用pow()替换整个函数,不需要重新编写它)

编辑: 在第一个例子中,你应该将它打破成多行,然后你会把它看作一个简单的错误。所以,像这样:

if(arg == 3)
  return arg;
else 
  return rec(arg + 1);

对于后代和良好的习惯,它应该是这样的(换句话说,使用括号)

if(arg == 3) {
  return arg;
}
else {
  return rec(arg + 1);
}

在你的第二个例子中,当你不应该使用递归时。只需要一个简单的Math.pow()调用即可。除非您想记录该行为,否则无需重新编写该函数。

编辑:

阅读你的评论后我的错误。我道歉。

流程如下:

console.log(power(2,3));

然后到行

if (3 == 0)
   return 1;
else
   return 2 * power(2, 3 - 1);  //power() returns 4, we return 8
   //same as: return 2 * power(2, 2);

然后到行

if (2 == 0)
   return 1;
else
   return 2 * power(2, 2 - 1);  //power() returns 2, we return 4
   //same as: return 2 * power(2, 1);

然后到行

if (1 == 0)
   return 1;
else
   return 2 * power(2, 1 - 1);  //power() returns 1, we return 2
   //same as: return 2 * power(2, 0);

然后到行

if (0 == 0)
   return 1;
else
   // moot  

答案 1 :(得分:3)

因为你没有告诉它。

function rec(arg){
     console.log(arg);
     if(arg == 3)return arg;
     else rec(arg + 1);        // < --- not a return statement
}
var i = rec(0);console.log(i);

else块不是返回语句。

至于你的第二个问题,那是因为0来自对某个地方的函数的嵌套调用:

base * power(base, exponent - 1);  // power(base, exponent - 1) would return 1 here, and base is probably 8 at that moment, so 8 * 1 would return you 8

答案 2 :(得分:1)

虽然之前的答案给出了事实上正确的信息,但它们并没有解决您误解的问题。

在这两种情况下,您都期望递归函数的返回是最后(最内部)调用的返回。这是不正确的。

从最里面的调用返回给第二个到最里面的调用;然后这一直持续到最后最外面的调用返回。调用者只能看到最外面的调用的返回值。

因此,在第一个示例中,您调用了rec(0)。 然后rec(0)拨打rec(1), 调用rec(2), 它调用rec(3)

然后rec(3)会将值3返回给rec(2)(因为它仍然在运行)。 然后rec(2)退出而不返回rec(1) 退出而不返回rec(0) 退出而不返回来电者。

因此调用者将返回视为未定义。

在第二种情况下,是的,power()的最后一次调用是power(2,0),它返回1 ...到power(2,1)的运行调用 它返回2到power(2,2)

的运行调用

......依此类推,直到调用者看到的最终返回为8。

顺便说一句,这不是“JavaScript中的递归”。这是递归。