JavaScript闭包之Fibonacci数列

  JavaScript闭包是学习JavaScript高级的必经之路。所以为了能够更好的理解闭包,记录一下关于闭包的几个小案例。Fibonacci函数是我们比较熟悉的函数了,一般我们是使用递归的方法去实现的。但是大家都知道,递归其实是对二叉树的深度遍历,这种方法写起来简单,但是效率并不是很高,这里给出三种实现Fibonacci数列的方法,分别是:递归法,闭包递归法,递推法。

递归法

    var count;
    var count=0;
    var fib=function(n){
        count++;
        if(n==1||n==2){
            return 1;
        }
        else{
            return fib(n-2)+fib(n-1);
        }
    }

  如上代码所示,递归法是最简单的解决方案,这里定义了一个count变量,是为了比较三种方法的执行效率。

闭包递推法

  闭包递推法就是利用闭包的原理,将一个数组(初始为【1,1】的Fibonacci数列),存在两个函数中间,并通过内部函数不断的调用的数组,使数组以全局变量的形式存储在内存中,这样不断扩展这个Fibonacci数列,最终求得所要的Fibonacci数,下面是代码示例:

    var count2=0;
    var fiba = (function(){
        var arr = [0,1,1];   //第0位只是占位,从第一位开始算起
        return function(n){
            count2++;   
            var res=arr[n]; /*因为内部引用了arr,并返回,导致arr一直在内存中*/
            if(res){
                return res;
            }else{
                arr[n]=fiba(n-1)+fiba(n-2);
                return arr[n];
            }   
        }
    })();

  虽然这里也是使用了递归,但是闭包大大减少了递归的次数,因为它是最先递归到fiba(3),就可以将fiba(3)存储到数组中,这样就可以根据数组中arr[3]+arr[2],得到fiba(4)的值,并存储在数组中,如此往复,便会得到最终结果。可以说,这是典型的用空间换时间的例子。

递推法

  要说递推法是效率最高的,它在一个for循环里不断地改变fiba(n-1)和fiba(n-2)的值,从而求得最终结果,代码如下:

    var count3 = 0;
    var fib3 = function (n) {
        var x = 1;
        var y = 1;
        var z = 0;
        if (n == 1 || n == 2) {
            return 1;
        } else {
            for (var i = 2; i < n; i++) {
                count3++;
                z = x + y;
                x = y;
                y = z;
            }
            return z;
        }
    };  

  这个方法应该也比较好理解,这里不做过多解释,下面是调用过程,并且给出了在同种情况下,它们各自count的值。

调用三种方法

onload=function(){
        var t = fib(8);
        alert(t);   //结果21
        alert(count);  //count=41
        var z=fiba (8);      
        alert(z);       //结果21
        alert(count2);    //count2=13
        var m = fib3(8);
        alert(m);           //结果21
        alert(count3);     //count3=6
    }

  从上面的实例可以看出,递推法的效率最高,其次是闭包,而递归法效率最低。闭包效率虽然相对递归法高了不少,但是这种方法,如果使用不当会造成内存泄露,如果我们要求一个很大的Fibonacci数,就会导致arr数组的所占的空间越来越大,而系统又因为它不断的被引用而无法释放内存,则会导致内存泄露。所以在使用闭包的时候,一定要注意这一点。

你可能感兴趣的:(JavaScript)