JavaScript使用递归的最佳方案

JavaScript使用递归的最佳方案_第1张图片

文章介绍

本文很简短,主要讲解的是使用递归时会遇到的坑,以及解决的办法。并不会讲解递归是什么和它的工作原理是什么!

内容

首先,我们以经典的阶乘函数为例:

function factorial (num) {
    if (num <= 1) {
        return 1;
    } else {
        return factorial(num-1) * num;
    }
}

以上代码正常使用并不会出现什么错误,但是如果有一天,我突然觉得这函数名太长了,想把它改改,改成如下:

function factorial (num) {
    if (num <= 1) {
        return 1;
    } else {
        return factorial(num-1) * num;
    }
}
//注:函数指的是函数对象,而不是标识符fac、factorial
//该函数引用+1 
var fac = factorial;
//该函数引用-1
factorial = null;
var n = fac(10); //报错!

因为函数的内部 return factorial(num-1) * num; 依然使用着标识符factorial,而为了让函数的引用数-1,我们已经让factorial置为null(这是很常见的做法)。因此报错!

所以这样写一个递归函数,代码的容错性是很低的!

因为我们可以利用arguments.callee来解决这个问题:

function factorial (num) {
    if (num <= 1) {
        return 1;
    } else {
        return arguments.callee(num-1) * num;
    }
}
var fac = factorial;
factorial = null;
var n = fac(10); //运行正常

但是,在严格模式下,不能使用arguments.callee这个属性。我在另一篇文章有介绍严格模式--详解JavaScript严格模式

因此在严格模式下,我们就必须要使用到函数名来调用,并且修改函数名后,依然能正常使用。
那么我们可以利用命名函数表达式来实现

var factorial = function f(num) {
    if (num <= 1) {
        return 1;
    } else {
        return f(num-1) * num;
    }
};
var fac = factorial;
factorial = null;
var n = fac(10); //运行正常

这样,我们就能随意更改函数名了!

注意:写成这样,全局作用域是访问不到f的
上面例子中,console.log(f); 将会报错!

你可能感兴趣的:(JavaScript使用递归的最佳方案)