Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个递归函数在JavaScript中究竟是如何工作的?_Javascript_Recursion - Fatal编程技术网

这个递归函数在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),等待电源返回

  • 当然,对电源(10,1)的调用将到达以下线路:

    return base * power(base, exponent - 1)
    
    …然后呼叫电源(10,0),等待电源返回

  • power(10,0)
    的调用将返回
    1
    ,然后由上面的调用2使用它来完成工作并返回
    10*1
    =
    10
    ,然后让您在上面的原始调用返回值
    10*10
    =
    100


  • 当试图理解这样的事情时,没有什么比使用调试器浏览代码更合适的了。在这个现代世界中,其中许多可能已经在您的计算机上。

    可视化递归中发生的事情的一种简单方法通常是:

  • 创建了对函数的调用堆栈:此进程需要一个适当的终止条件才能结束(否则将出现无限递归,这是邪恶的
  • 从堆栈中弹出单个结果:每个结果用于计算下一步,直到堆栈为空
  • 也就是说,如果base=5,exponent=3,调用堆栈是(顶部的最后一个元素):

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

    请注意,这里的函数是按相反顺序计算的:首先是幂(5,0),然后是幂(5,1),依此类推。。每次计算后,堆栈的一个元素被释放(即内存被释放)


    希望有帮助:)

    这条线和它的分辨率真的让我绊倒了:

    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;