JavaScript递归


那么什么叫递归呢?所谓递归函数就是在函数体内调用本函数。最简单的例子就是计算阶乘。0和1的阶乘都会被定义为1,更大的数的阶乘是通过计算1*1*...来求得的,每次增加1,直至达到要计算阶乘的那个数。

递归的缺点:如果递归函数的终止条件不明确或者缺少终止条件会导致函数长时间运行,是用户界面处于假死状态。值得注意的是:浏览器对递归的支持熟练与JS调用栈大小直接相关,当使用太多递归甚至超过最大调用栈容量时,浏览器会报错误信息,各个浏览器对报错的提示信息也不一样。

下面我们先来看一下一个经典的递归阶乘函数:

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

上面的的这个函数表面上没有什么问题,但是以下的代码却可能会导致问题:

var f = test; test = null; console.log(f(2));//报错 Uncaught TypeError: test is not a function

指向原始函数的引用就剩下一个,当调用f()函数时,而test已经不再是一个函数了,所以会导致错误,但是我们可以使用arguments.callee来解决这个问题。

大家都知道,arguments.callee是一个指向正在执行的函数的指针,因此可以用它来实现函数的递归调用,看如下代码:

function test(num){
    if(num <= 1){
        return 1;
    }else{
        return num * arguments.callee(num-1);
    }
}

哈哈,上面的代码是不是已经完美的解决了问题呢?

NO,NO,NO....

在严格模式下,不能通过脚本来访问arguments.callee,访问这个属性会导致错误的。哎!说到这里宝宝心里也累啊,但是没有关系,还是有方法解决的,可以使用命名函数表达式来达成相同的结果。代码如下:

var fs = (function test(num){
    if(num <= 1){
        return 1;
    }else{
        return num * test(num-1);
    }
    //下面这两行代码完全不会影响运行,不信?那你可以试试
    //var f = test;
    // test = null;
});
console.log(fs(2));

 

这样即使函数赋值给了另外一个变量,f()函数依然是有效的,所以递归调用能正常完成。而且这种方式在严格模式和非严格模式下都可以使用哦。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM