首页 > 代码库 > JavaScript ---- 闭包(什么是闭包,为什么使用闭包,闭包的作用)

JavaScript ---- 闭包(什么是闭包,为什么使用闭包,闭包的作用)

经常被问到什么是闭包?

说实话闭包这个概念很难解释。JavaScript权威指南里有这么一段话:“JavaScript函数是将要执行的代码以及执行这些代码作用域构成的一个综合体。在计算机学术语里,这种代码和作用域额综合体叫做闭包。”。言外之意所有的JavaScript函数都是闭包。

有人会说,这个解释不对。我们经常说的闭包应该像下面的一串代码:

    var f1 = function(){
        var a=1;
        return function f2(){
            a++;
            alert(a)
        }
    }
    var b = f1();
    b();            // 2
    b();            // 3

是的,这是闭包中的一个经典例子,也是我们通常说的闭包。在这段代码中,b便是闭包f2的函数。

为什么使用闭包?

写到这里,我们不得不先理解下JavaScript的特殊变量作用域和JavaScript的垃圾回收机制了。

(1)、什么是变量作用域呢?一个变量的作用域是程序中第一这个变量的区域。JavaScript的变量分为“全局变量”和“局部变量”。

全局变量:全局变量的作用域是全局性的,即在JavaScript代码中,它处处都有定义。我经常写一个“a=1”,这个变量“a”就被定义成了全局性的了。

局部变量:在函数之内声明的变量,就只在函数体内部定义,它的作用域是局部性的。函数的参数也是局部变量,它们只在函数体内有定义。在函数体内,局部变量的优先级比同名的全局变量要高,例如:

var a =1;
    function f1(){
        var a=2;
        alert(a);
    }
    f1(); // 2

那么如果我把 变量“a”变成局部变量的话,例如:

function f1(){
        var a=2;
    }
    alert(a); 

就会报如下图的错误:

技术分享

有人会说,怎么 可能会有这么奇葩的需求,下面我举个例子,大家就会发现,其实我们还是用过的。

闭包实例:

技术分享

当我“点击”按钮时,效果如下:

技术分享

代码我们也许会这么处理:

$(‘.button‘).click(function(){
        var length = $(‘.list‘).find(‘li‘).length;
        var timer =null;
        for(var i=0;i<length;i++){
            timer=setTimeout(function(){
                if(i>length){
                    clearInterval(timer);
                }
                $(‘.list li‘).eq(i).css({‘-webkit-transform‘:‘scale(‘+(i+1)+‘)‘,‘marginLeft‘:(i+1)*50 +‘px‘})
                console.log(i)
            },i*2000)
        }
    })

运行之后你会发现,并没有出现我们想要的效果,打印“i”,发现,技术分享,怎么会输出了3次“3”呢,其实是for()里面的变量i的作用域问题,i的作用域仅在for循环的函数体内,怎么才能实现这个效果呢,我们可以做个小的改动,代码如下:

$(‘.button‘).click(function(){
        var length = $(‘.list‘).find(‘li‘).length;
        var timer =null;
        for(var i=0;i<length;i++){
            timer=setTimeout((function(i){
                if(i>length){
                    clearInterval(timer);
                }
                $(‘.list li‘).eq(i).css({‘-webkit-transform‘:‘scale(‘+(i+1)+‘)‘,‘marginLeft‘:(i+1)*50 +‘px‘})
                //console.log(i)
            })(i),i*2000)
        }
    })

把“i”,当做参数传进去,这便构成了闭包。

(2)、什么是JavaScript的垃圾回收机制呢?

答:JavaScript不要求手动的释放内存,它使用一种称为垃圾收集的方法,JavaScript的解释器可以检测到何时程序不再使用一个对象了。当它确定了,一个对象是无用的时候,JavaScript的解释器就把该对象所占用的内存释放掉了。

所以综上所述,就不难理解,在f1函数里定义一个局部变量a,在f1函数外面,变量a会找不到,因为,它被释放掉了。

我们是不是可以这么认为“闭包的作用(或者定义)就是使私有的变量(也可以理解为局部变量)能够被多个函数共享,而不被JavaScript的解析器自动的从内存中释放掉

闭包的缺点:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

 楼楼不才,对闭包的理解目前就这么多,等深入学习了,会再补充和修正的。推荐大家可以看看“阮一峰”老师写的“学习Javascript闭包(Closure)”,链接:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

JavaScript ---- 闭包(什么是闭包,为什么使用闭包,闭包的作用)