从举个例子开始吧:
function factorial (n) { return !(n > 1) ? 1 : factorial(n - 1) * n; } [1,2,3,4,5].map(factorial); //返回:1,2,6,24,120
我想了很久!正确的值不少应该是返回 1,2,6,12,20 么!
后来查阅了不少资料,去翻看说是递归函数
原理:
首先我们看2个函数
function factorial (n) { return !(n > 1) ? 1 : factorial(n - 1) * n; } [1,2,3,4,5].map(factorial); //返回:1,2,6,24,120 [1,2,3,4,5].map(function (n) { return !(n > 1) ? 1 : /* what goes here? */ (n - 1) * n; }); //返回 1,2,6,12,20
这里我们同样的执行了map 去,但是返回的是2个结果!
为什么呢?
这就涉及到调用本身!上面2个的差别是,第一个
factorial(n - 1) * n;
去调用了一次本身
一次调用自身时都会开辟一块新的内存用来保存之前函数中的值并压入栈中,所以说这里你可以看成是另一个新的函数在运行,新函数中的各种值、变量等等都跟调用之前的函数没什么关系,虽然它调用的就是它自己。(当然了,如果上一个函数需要新函数的return值,那还是有点关系的)
递归调用的那一刻,个人觉得有点像是中断一样,就是碰到一个递归调用了,我就把眼前的函数运行先停下来,先去执行新的函数,等新的函数执行完了,控制权又回到了我的手里,我再继续干我没干完的工作,不知道这算不算是异步啊~~(还是小白一只,对许多概念也还摸不清,只能浅谈一下自己的理解,若有大佬,请不吝赐教)
我们可以用debugger来看下他的执行过程!
function factorial (n) { debugger; return !(n > 1) ? 1 : factorial(n - 1) * n; } [1,2,3,4,5].map(factorial); //执行数字过程 1,2,1,3,2,1,4,3,2,1,5,4,3,2,1
那么我们可以理解下!
function factorial (n) { return !(n > 1) ? 1 : factorial(n - 1) * n; }
//1和2就不算了,很简单,直接4开始,毕竟有代表性
第1步、计算4
function factorial (3) { return !(3 > 1) ? 1 : factorial(3 - 1) * 3; }
第2步、计算3
function factorial (3) { return !(3 > 1) ? 1 : factorial(3 - 1) * 3; }
第3步、计算2
//上面我们需要先算 factorial(3 - 1) function factorial (2) { return !(2 > 1) ? 1 : factorial(2 - 1) * 2; }
第4步、计算1
//上面我们需要先算 factorial(2 - 1) function factorial 1) { return !(1 > 1) ? 1; }
好了,
我们第4步得到的是1,无法递归了!永远都是1 那么=1
然后我们回归到第3步, factorial(2 - 1) * 2
=1*2
那么=2
然后我们再回归到第2步factorial(3 - 1) * 3
=2*3 那么=6
然后我们再回归到第1步factorial(4 - 1) * 4
=6*4 那么=24
如果还不明白!我们再浅显一点,从下往上,
既然f(1)=1, 那么f(2-1)*2 就是 f(1)*2
那么我们就已知
f(2)=2; 那么f(3-1)*3=f(2)*3 已知f(2)=2 那么久得出等于6
已知f(3)=6 那f(4-1)*4 =6*4=24
已知f(4)=24 那f(5-1)*2=24*5=120
factorial(1)=1
factorial(2)=factorial(1)*2=2
factorial(3)=factorial(2)*3=6
factorial(4)=factorial(3)*4=24
factorial(5)=factorial(5)*4=120
-
相关内容
-
发表评论