这个递归函数究竟是如何在JavaScript中运行的?

时间:2011-07-21 09:23:42

标签: javascript recursion

我有一个递归函数的例子,我不明白的是事情发生的顺序:

function power(base, exponent) {
  if (exponent == 0)
    return 1;
  else
    return base * power(base, exponent - 1);
}

该函数何时返回值,在所有过程结束时或每次?

7 个答案:

答案 0 :(得分:9)

一种简单的方法可视化递归一般中发生的事情是这样的:

  1. 创建函数调用的堆栈:此过程需要一个正确的终止条件才能结束(否则你将有无限递归, evil )< / LI>
  2. 单个结果弹出从堆栈中出来:每个结果用于计算下一步,直到堆栈为空
  3. 即。如果base = 5且exponent = 3,则调用堆栈是(最后一个元素在顶部):

    5*(5*(5*1))
    5*(5*(5*power(5, 0)))
    5*(5*power(5, 1))
    5*power(5, 2)
    power(5, 3)
    

    然后每个被调用的函数都有实参,并准备返回一个值(顶部的第一个元素):

    5*(5*(5*1))
    5*(5*5)
    5*25
    125
    

    请注意,此处的函数以顺序进行计算:首先power(5, 0),然后是power(5, 1),依此类推。在每次计算之后,堆栈的一个元素被释放(即释放内存)。

    希望有所帮助:)

答案 1 :(得分:8)

通常有助于理解像这样的递归函数,就像在代数类中一样。考虑:

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

答案 2 :(得分:6)

这里的关键是power正在调用自己完全可以调用任何其他函数的方式。所以当它这样做时,它会等待函数返回并使用它的返回值。

所以,如果你这样做

var x = power(10, 2);
  1. 您对power的来电将转到此行:

    return base * power(base, exponent - 1)
    

    ...并致电power(10, 1),等待返回。

  2. power(10, 1)的调用当然会到达这一行:

    return base * power(base, exponent - 1)
    

    ...并致电power(10, 0),等待返回。

  3. power(10, 0)的调用将返回1,然后上述#2中的调用将其用于完成其工作并返回10 * 1 = 10 ,然后让您在上面#1中的原始通话返回值10 * 10 = 100

  4. 当试图理解这样的事情时,没有什么比用调试器来浏览代码了。在这个现代世界中,you have plenty to choose from,其中许多可能已经在您的计算机上。

答案 3 :(得分:2)

为了更好地进行可视化,只需将函数调用替换为函数体(例如,可以是伪代码)。

function power(base, exponent) {
  if (exponent == 0)
    return 1;
  else
    return base * power(base, exponent - 1);
}

power(5, 3)扩展到此

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;

答案 4 :(得分:0)

与任何递归函数一样,在计算返回值时会发生特定“实例”的返回。这意味着将计算递归版本。

因此,如果传入4的指数,则某时会执行4个正在执行的函数副本。

答案 5 :(得分:0)

这条线及其分辨率确实让我兴奋不已:

return base * power(base, exponent - 1)

我得到指数递减直到它满足基本情况,但是当你多了多少时 基本乘以递归函数调用,我一直在思考“函数如何通过自身多次(基本争论)?”,它在哪里完全正确,因为调用base * power(base,exponent - 1)并不是'看起来像标准的循环结构。如何调用具有两个论证的函数,它如何知道跳过指数论证并将基数乘以基数?

答案 6 :(得分:0)

从数学角度来看:

让x =基数, 设n =指数

x*x^(n-1) = x^n

因为

x^1*x^n-1=x^n(类似术语的指数加在一起)

与以下内容相同:

base * base*exponent-1.