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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM