1. 目的
- 处理一些循环相关问题时,可以让代码更加简洁
打开编程解题的一种思路,很多算法都会用到递归,包括汉诺塔、快速排序。
2. 概念
3. 限制
递归需要设置边界:即什么时候结束。条件自己决定。
//函数执行十次就结束function demo(num){if(num <1){return;}console.log(num);demo(num -1);}demo(10);
4. 递归的经典应用
计算某数的阶乘
function factorial (num) {if (num == 1) {return 1}return num * factorial(num - 1)}console.log(factorial(5));//120
求出斐波那契数列的第n项
//斐波那契数列是指一堆有规律的数字,第一个和第二个都是1,从第三项开始,该项数字等于前两项之和: 1 1 2 3 5 8 13 21 34 …function fib (n) {n = parseInt(n);if (n < 1) {return 0}if (n == 1 || n == 2) {return 1}return fib(n - 1) + fib(n - 2)}console.log(fib(6));//8
类似斐波那契数列问题
台阶走法问题:有n个台阶,从第一阶开始走,每次可以走一个或两个台阶,问,到第n阶有多少中走法
有一对雌雄兔子,从第三个月开始就每个月生一对雌雄兔子,新兔子又会在第三个月开始生,求第n月后有多少对兔子
5. 传统递归的缺点
不利于维护,在修改函数名的时候,需要修改两处,容易忘记,导致错误
- 把函数指向其他变量,并清空原先函数的情况下,函数发生错误
var anotherFunction = fatorial;factorial = null;alert(anotherFunction(4)); //出错
6. arguments.callee
使用argumes.callee可以解决这个问题。arguments.callee是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用。
通过function factorial(num) {if (num <= 1) {return 1;}else {return num * arguments.callee(num - 1);}}
arguments.callee代替函数名,可以确保无论怎样调用函数都不会出现问题。7. 命名函数表达式
但在严格模式下,不能通过脚本访问arguments.callee,访问这个属性会导致错误,不过可以使用命名函数表达式来达成相同的结果。var factorial = (function f(num) {if (num <= 1) {return 1;}else {return num * f(num - 1);}});
