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

时间:2016-10-13 02:19:22

标签: javascript recursion

我正在尝试学习递归,我在互联网上找到了这个示例函数。我很难完全了解这里发生的事情。对我来说最让人困惑的部分是,我在最后一个块中放置了几个警报命令(参数减少到2),以查看" first"的值。和"第二"是什么时候到了这一点。值出现在" 4"和" 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);

2 个答案:

答案 0 :(得分:4)

您阅读的特定功能是一块垃圾无济于事。你无法有效地理解它并不是你的错。

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

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 * - 这是一个糟糕的功能*呕吐*你不应该注意它。

考虑以下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。使用pre-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

答案 1 :(得分:3)

第一次通过总和,它抓住1和2,但是args.length == 4,所以它返回1 + 还有待决定的东西

要找到还有待决定的东西,该函数再次调用sum(递归),但切掉第一个元素,所以我们留下了2,3,4 这一次,它抓住2和3,但args.length == 3,所以它说还有待决定的东西是2 + 别的东西

要找到别的东西,该函数再次调用sum(递归),但再次切掉第一个元素。上次它有2,3,4,所以这次它有3,4。

这一次,args.lenght == 2,所以它进去了,然后加起来3 + 4 == 7.然后你的警报第一次被称为 因为这是第一次它已经完成了代码的这一部分。最后它返回7.这是三层深。

呼!现在我们知道别的东西 = 7,这意味着还有待决定的东西 = 2 + 其他东西 = 2 + 7 = 9,所以我们会回来的。这是两层深。

最后,我们从sum()的第一层返回1 + *仍有待决定的东西= 1 + 9 = 10.

它警告7然后返回10的原因是因为只有在args.length == 2时才会调用警报。