这个递归函数在JavaScript中究竟是如何工作的?
我有一个递归函数的例子,但我不明白事情发生的顺序:这个递归函数在JavaScript中究竟是如何工作的?,javascript,recursion,Javascript,Recursion,我有一个递归函数的例子,但我不明白事情发生的顺序: function power(base, exponent) { if (exponent == 0) return 1; else return base * power(base, exponent - 1); } 函数何时返回值,在所有过程结束时或每次返回值?与任何递归函数一样,在计算返回值时,从特定“实例”返回值。这意味着将计算递归版本 因此,如果你传入一个4的指数,那么在某个点上,一次将执行4个函数副本。像在
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
函数何时返回值,在所有过程结束时或每次返回值?与任何递归函数一样,在计算返回值时,从特定“实例”返回值。这意味着将计算递归版本
因此,如果你传入一个4的指数,那么在某个点上,一次将执行4个函数副本。像在代数类中那样计算,这通常有助于理解此类递归函数。考虑:
power(3, 4)
= 3 * power(3, 3)
= 3 * (3 * power(3, 2))
= 3 * (3 * (3 * power(3, 1)))
= 3 * (3 * (3 * (3 * power(3, 0))))
= 3 * (3 * (3 * (3 * 1)))
= 3 * (3 * (3 * 3))
...
= 81
这里的关键是,
power
正以调用任何其他函数的方式调用自己。因此,当它这样做时,它会等待函数返回并使用其返回值
所以如果你这样做了
var x = power(10, 2);
return base * power(base, exponent - 1)
…然后呼叫电源(10,1),等待电源返回return base * power(base, exponent - 1)
…然后呼叫电源(10,0),等待电源返回power(10,0)
的调用将返回1
,然后由上面的调用2使用它来完成工作并返回10*1
=10
,然后让您在上面的原始调用返回值10*10
=100
当试图理解这样的事情时,没有什么比使用调试器浏览代码更合适的了。在这个现代世界中,其中许多可能已经在您的计算机上。可视化递归中发生的事情的一种简单方法通常是:
希望有帮助:)这条线和它的分辨率真的让我绊倒了:
return base * power(base, exponent - 1)
我得到指数递减,直到它满足基本情况,但是当你多重
基函数乘以递归函数调用,我一直在想“函数是如何通过自身(基参数)将基函数多重化的?”它到底在哪里做的,因为调用基*幂(基,指数-1)看起来不像标准的循环构造。它如何调用一个包含两个参数的函数,它如何知道跳过指数参数并将基数乘以基数?从数学角度看: 设x=base, 设n=指数
x*x^(n-1)=x^n
因为
x^1*x^n-1=x^n
(类似术语的指数相加)
这与:
base * base*exponent-1.
为了更好地可视化,只需将函数调用替换为函数体(例如,可能是伪代码)
电源(5,3)
扩展到此
现在情况清楚了。一切都变得像下面这样..
// 1
function power(5, 3){
return 5 * function power(5, 2){
return 5 * function power(5, 1){
return 5 * ( function power(5, 0){
return 1;
} )
}
}
}
// 2
function power(5, 3){
return 5 * function power(5, 2){
return 5 * ( function power(5, 1){
return 5 * 1;
} )
}
}
// 3
function power(5, 3){
return 5 * ( function power(5, 2){
return 5 * 5 * 1;
} )
}
// 4
function power(5, 3){
return ( 5 * 5 * 5 * 1 );
}
// 5
5 * 5 * 5 * 1;
您可以只记录参数。例如,在声明power之后立即添加
console.log(base,exponent)
。一切都将被揭露@TJHeuval:更好的方法是,使用适当的调试器遍历它printf
-风格的调试在2011年几乎没有一席之地!:-)离题,但请注意,如果传递负指数,则您的power
函数将失败。它将不断地用更低的负指数调用自己,直到达到递归极限,并以“太多递归”错误退出。在其他一些环境中,我们知道它的另一个名称:堆栈溢出!;-)递归函数在某种程度上类似于一个循环。您需要定义一个中止条件。您的条件是指数变为1。@Ray Toal,因此在函数达到其基本情况之前,它会堆叠函数,当它有一个最终数字而不是另一个函数时,它会自上而下地计算所有堆叠的函数?是的,在这种情况下,函数是“堆叠”的,在达到基本情况之后,它们是“展开”的然后应用乘法。答案中括号的嵌套显示了堆叠和展开,虽然有点神秘,但它确实存在。虽然链接中的示例使用了斐波那契函数,这个解释适合理解递归函数是如何工作的https://www.youtube.com/watch?v=zg-ddPbzcKM
因此,如果理解正确,它需要功率(3,3)
并将第一个返回值3*功率(3,2)放在堆栈上然后3*幂(3,1)代码>直到满足停止条件(这是一个最终数字而不是另一个函数),并从下到下计算堆栈中的所有函数?是;顺便说一句,无限(或太深)递归是众所周知的堆栈溢出错误(:)的最常见原因之一
base * base*exponent-1.
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
function power(5, 3) {
// exponent 3 is not 0
// return 5 * power(5, 3-1)
return 5 * function power(5, 2) {
// exponent 2 is not 0
// return 5 * power(5, 2-1)
return 5 * function power(5, 1) {
//exponent 1 is not 0
// return 5 * power(5, 1-1)
return 5 * function power(5, 0){
//exponent 0 is 0
return 1;
}
}
}
}
// 1
function power(5, 3){
return 5 * function power(5, 2){
return 5 * function power(5, 1){
return 5 * ( function power(5, 0){
return 1;
} )
}
}
}
// 2
function power(5, 3){
return 5 * function power(5, 2){
return 5 * ( function power(5, 1){
return 5 * 1;
} )
}
}
// 3
function power(5, 3){
return 5 * ( function power(5, 2){
return 5 * 5 * 1;
} )
}
// 4
function power(5, 3){
return ( 5 * 5 * 5 * 1 );
}
// 5
5 * 5 * 5 * 1;