需要帮助理解这个递归函数

Need help understanding this recursion function

本文关键字:递归函数 助理 帮助      更新时间:2023-09-26

我正在尝试学习递归,我在网上找到了这个示例函数。我不太明白这里到底发生了什么。最让我感到困惑的部分是,我在最后一个块(其中参数减少为2)中放置了两个警报命令,以查看当它到达这一点时"first"answers"second"的值是什么。出现的值是"4"answers"3",我在返回之前将这两个值相加。结果是7。然后实际返回的是相同的方程,它给出的答案是10。有谁能给我解释一下这是如何工作的,它是如何最终到达10的?

function sum() {
    var args = Array.from(arguments);
    var first = args[0];
    var second = args[1];
    if(args.length === 2) {
        alert("first:" + first + " second:" + second );
        alert("Sum: " + (first+second) ) //this alerts 7
        return first + second;           //returned value is 10
    }
    return first + sum.apply(null, args.slice(1));
}
var results = sum(1,2,3,4);
console.log(results);

第一次通过sum,它获取1和2,但args。长度== 4,所以它返回1 + 还有待确定的值

要找到仍有待确定的,该函数再次调用sum(递归),但将第一个元素切片,因此我们剩下2,3,4这次,它捕获了2和3,但是是参数。长度== 3,所以它表示还有待决定的东西是2 + 另一个

要找到另一个,函数再次调用sum(递归),但再次切掉第一个元素。上次是2,3,4,所以这次是3,4

这次是args。长度== 2,所以它进去,加起来3+4 == 7。然后你的警报第一次被调用因为这是它第一次经过这段代码。最后它返回7。这是三层深。

唷!现在我们知道 = 7,这意味着还有待决定 = 2 + = 2 + 7 = 9,所以我们将返回它。这是两层的深度

最后,我们返回1 + *一个有待决定的数= 1 + 9 = 10,来自sum()的第一层

它警告7,然后返回10的原因是因为你的警告只在参数。长度== 2

如果你所阅读的特定函数是一堆垃圾,这并没有什么帮助。你不能很好地理解它不是你的错。

首先,您找到的函数不是总函数 -意思是,它不会对其域的所有输入产生合理的结果。

sum();
// RangeError: Maximum call stack size exceeded
sum(1);
// RangeError: Maximum call stack size exceeded

这太荒谬了。我们可能期望sum()返回0(可能是NaN),但sum(1)应该肯定返回1

其次,这个函数使用的是Array.from,这使它处于ES6+时代的代码…

function sum() {
   // are you f*$@ing joking me??
   var args = Array.from(arguments);

…使用Array.from,但仍然使用旧的arguments对象?哇。

不管怎样…*wretch*, *gag* -这是一个糟糕的函数*puke*你不应该关注它。


考虑以下sum函数实现。我保证你将能够毫不费力地理解这些。

function sum(numbers) {
  if (numbers.length === 0)
    return 0;
  else
    return numbers[0] + sum(numbers.slice(1));
}
console.log(sum([]));                  //= 0
console.log(sum([1]));                 //= 1
console.log(sum([1,2,3,4,5,6,7,8,9])); //= 45

它的工作方式只有有一点不同,接受一个数组的数字,而不是可变参数。

// sum must be called like this now
sum([1,2,3,4,5,6,7,8,9]);
// instead of:
sum(1,2,3,4,5,6,7,8,9);

好吧,也许支持可变接口是必要的。还有更好的方法——特别是如果你可以使用ES6

// ES6 using spread syntax
function sum(n,...ns) {
  if (n === undefined)
    return 0;
  else
    return n + sum(...ns);
}
console.log(sum());                  //= 0
console.log(sum(1));                 //= 1
console.log(sum(1,2,3,4,5,6,7,8,9)); //= 45

好吧,也许你不能用ES6。还有一个更好的方法,使用es6之前版本

// ES5; relying upon old arguments object
function sum(/*numbers*/) {
  if (arguments[0] === undefined)
    return 0;
  else
    return arguments[0] +
      sum.apply(null, Array.prototype.slice.call(arguments, 1));
}
console.log(sum());                  //= 0
console.log(sum(1));                 //= 1
console.log(sum(1,2,3,4,5,6,7,8,9)); //= 45