我正在尝试学习递归,我在互联网上找到了这个示例函数。我很难完全了解这里发生的事情。对我来说最让人困惑的部分是,我在最后一个块中放置了几个警报命令(参数减少到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);
答案 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时才会调用警报。