我正在查看此网站:http://rosettacode.org/wiki/Fibonacci_sequence#JavaScript并看到了这个程序:
function fib(n) {
return function(n,a,b) {
return n>0 ? arguments.callee(n-1,b,a+b) : a;
}(n,0,1);
}
这是如何工作的,这两个参数(a和b)有什么帮助。我追踪它仍然无法弄清楚它是如何工作的
答案 0 :(得分:9)
在function(n,a,b)
中,n
用作倒数计数器,a
b
存储两个连续的斐波纳契数,用于计算下一个,所以当{{ 1}}达到0,你有n
作为第n + 1个斐波纳契数(因为真正的斐波那契有两个1作为开头)。
例如,n = 4:
a
如您所见,a和b的值始终等于斐波纳契数。此外,这与功能编程非常相似(如网站所述 Scheme 程序员)。
答案 1 :(得分:1)
a
和b
是新定义的匿名函数的参数。
我会看看这个page,它是关于arguments对象的文档。来自文档的arguments.callee是对当前函数的引用。必须这样做,因为它们在匿名函数中工作,所以它实际上没有名称(他们知道)。
好像他们递归地调用他们(匿名)定义的深度为n
的函数。在此过程中,他们正在计算fib数,并且一旦达到a
的深度,它们就会返回值n
。传递给函数的初始值为(n,0,1)
答案 2 :(得分:1)
正如here所解释的, arguments.callee 指的是您所在的当前功能。由于您所在的功能是匿名,这是唯一的调用函数并实现递归的方法。
特定函数通过递归调用内部函数来计算Fibonacci sequence。
答案 3 :(得分:1)
a
和b
代表序列的当前编号和序列的下一个编号,从0
和1
开始。 n
是一个倒计时器,用于指定将返回斐波纳契序列的哪个元素(EG:n = 10
将返回55
)。
此函数通过接受参数n
来工作,这意味着它将计算序列的第n个数:
function fib(n) {
然后代码定义一个函数,用于计算序列中的下一个数字:
function(n,a,b) {
return n>0 ? arguments.callee(n-1,b,a+b) : a;
}
基本上,这个匿名函数每次执行时都会向下计数n
,同时将a
和b
移动到序列中的下一个数字。如果n
等于0
,则序列已完成,并返回当前数字a
。
arguments.callee指的是当前正在执行的函数,因此代码只是意味着使用新参数回调自身。换句话说,开始“循环”的下一次迭代。
最后,通过说(n,0,1);
,代码实际上使用参数fib
调用n,0,1
。我从上面的代码片段中遗漏的return
语句获取了匿名函数的返回值,并将其返回给fib
的调用者。
也就是说,以这种方式使用递归对于没有尾调用优化的JavaScript等语言是低效的。对于大n
,最好使用标准循环结构而不是递归来编写它。
答案 4 :(得分:-2)
我看到一些可能导致混淆的问题。递归函数模式的短手和尾部优化。
问题可能出在代码的简写版本中。为了清楚起见,重写了以下内容。
尾部优化用于通过添加累加器部分来驯服递归函数的堆栈使用。这是一种常见的模式,但却忽略了可读性。这是重复功能。
特别注意,与循环迭代相比,性能更好。
function fib(n) {
function recur(n, a, b) {
if (n > 0) {
return recur(n - 1, b, a + b);
} else {
return a;
}
}
return recur(n, 0, 1);
}

关于参数, n 是迭代计数器, a 和 b 是斐波纳契的序列部分。