美文网首页程序员Web前端之路让前端飞
JavaScript使用递归的最佳方案

JavaScript使用递归的最佳方案

作者: 不洗头的野人 | 来源:发表于2017-03-29 09:03 被阅读163次

    文章介绍

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

    内容

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

    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使用递归的最佳方案

        本文链接:https://www.haomeiwen.com/subject/wwisottx.html