所谓递归:就是函数调用函数本身
在数学中,常常使用到阶乘,累加之类的,这就是经典的递归函数了
例如:输入一个数,要计算这个数的阶乘
首先来分析一下:要计算阶乘,首先我们要确定阶乘的输入数是多少,例如是 n;
那么:计算公式是什么呢?
假设值为 f(n) , 那么
f(n) = 1*2*3*4*5*6*7*8*9*10*.....*n;
这就难办了,要一直乘法,何时是个头呢?
再分析一下:f(n) = f(n-1)*n 只要n>1,算法永远成立
好了,那我们就开始来算吧,从后往前推,知道n=1 为止,这个计算就完成了
我们不需要去考虑要写多少算式,因为这是计算机帮我们写,不需要关心这些;只管照着这个逻辑去做就行
1 <script> 2 function jiecheng(n) { 3 if (n == 1) { 4 return 1; 5 } else { 6 return jiecheng(n - 1) * n; 7 } 8 } 9 10 var jieguo1 = jiecheng(5); 11 var jieguo2 = jiecheng(8); 12 console.log(jieguo1); 13 console.log(jieguo2); 14 </script>
增加一个新函数,使用新函数调用,仍然没有问题
1 <script> 2 function jiecheng(n) { 3 if (n == 1) { 4 return 1; 5 } else { 6 return jiecheng(n - 1) * n; 7 } 8 } 9 10 var jiecheng1 = jiecheng; // 创建一个新函数,继续调用,仍然没有问题 11 var jieguo1 = jiecheng1(5); 12 var jieguo2 = jiecheng1(8); 13 console.log(jieguo1); 14 console.log(jieguo2); 15 </script>
对旧函数进行清空,然后再调用;
<script> function jiecheng(n) { if (n == 1) { return 1; } else { return jiecheng(n - 1) * n; } } var jiecheng1 = jiecheng; // 创建一个新函数,继续调用,仍然没有问题 jiecheng = null; // 改变原先函数的指向,则会出错 var jieguo1 = jiecheng1(5); var jieguo2 = jiecheng1(8); console.log(jieguo1); console.log(jieguo2); </script>
原因:在函数的内部,我们仍然使用原来函数的函数名,即原来的指针;但是现在指针指向null 了,所以报错
解决这个问题,我们会用到另外一个指针函数:arguments.callee , 表示指向当前运行函数的指针;即当前正在运行的函数为sum,那么它指向sum ;如果当前运行的函数是hehehe,那么它指向heheh,它是一个变化的指针
修改之后,我们得到的代码如下:这样,即使改变了原先函数的指向,也不会出现错误了
1 <script> 2 function jiecheng(n) { 3 if (n == 1) { 4 return 1; 5 } else { 6 return arguments.callee(n - 1) * n; 7 } 8 } 9 10 var jiecheng1 = jiecheng; // 创建一个新函数,继续调用,仍然没有问题 11 jiecheng = null; // 改变原先函数的指向 12 var jieguo1 = jiecheng1(5); 13 var jieguo2 = jiecheng1(8); 14 console.log(jieguo1); 15 console.log(jieguo2); 16 </script>
但是,在严格模式下,js 不允许使用 arguments.callee ,我们再来看另外一种情况
1 <script> 2 var jiecheng = (function f1(n) { 3 if (n == 1) { 4 return 1; 5 } else { 6 return f1(n - 1) * n; 7 } 8 }); 9 10 var jiecheng1 = jiecheng; // 创建一个新函数,继续调用,仍然没有问题 11 jiecheng = null; // 改变原先函数的指向 12 var jieguo1 = jiecheng1(5); 13 var jieguo2 = jiecheng1(8); 14 console.log(jieguo1); 15 console.log(jieguo2); 16 </script>
这里,使用命名表达式来完成,即使把 jiecheng() 赋值为null 了,也不影响命名表达式内部的指针,所以能够执行