递归函数是在一个函数里面通过函数名字调用自身的情况下构成的。

  1. function factorial(num) {
  2. if (num <= 1) {
  3. return 1;
  4. }
  5. else {
  6. return num * factorial(num - 1);
  7. }
  8. }

这是一个经典的递归阶乘函数。

1. 传统递归的缺点

  • 不利于维护,在修改函数名的时候,需要修改两处,容易忘记,导致错误

  • 把函数指向其他变量,并清空原先函数的情况下,函数发生错误

  1. var anotherFunction = fatorial;
  2. factorial = null;
  3. alert(anotherFunction(4)); //出错

2. arguments.callee

使用 argumes.callee 可以解决这个问题。 arguments.callee 是一个指向正在执行的函数的指针,因此可以用它来实现对函数的递归调用。

  1. function factorial(num) {
  2. if (num <= 1) {
  3. return 1;
  4. }
  5. else {
  6. return num * arguments.callee(num - 1);
  7. }
  8. }

通过 arguments.callee 代替函数名,可以确保无论怎样调用函数都不会出现问题。

3. 命名函数表达式

但在严格模式下,不能通过脚本访问 arguments.callee,访问这个属性会导致错误,不过可以使用命名函数表达式来达成相同的结果。

  1. var factorial = (function f(num) {
  2. if (num <= 1) {
  3. return 1;
  4. }
  5. else {
  6. return num * f(num - 1);
  7. }
  8. });