js閉包的用途

我們來看看閉包的用途。事實上,通過使用閉包,我們可以做很多事情。比如模擬面向對象的代碼風格;更優雅,更簡潔的表達出代碼;在某些方面提升代碼的執行效率。


1 匿名自執行函數


我們知道所有的變量,如果不加上var關鍵字,則默認的會添加到全局對象的屬性上去,這樣的臨時變量加入全局對象有很多壞處,
比如:別的函數可能誤用這些變量;造成全局對象過於龐大,影響訪問速度(因爲變量的取值是需要從原型鏈上遍歷的)。
除了每次使用變量都是用var關鍵字外,我們在實際情況下經常遇到這樣一種情況,即有的函數只需要執行一次,其內部變量無需維護,
比如UI的初始化,那麼我們可以使用閉包:

    var datamodel = {    
        table : [],    
        tree : {}    
    };    
         
    (function(dm){    
        for(var i = 0; i < dm.table.rows; i++){    
           var row = dm.table.rows[i];    
           for(var j = 0; j < row.cells; i++){    
               drawCell(i, j);    
           }    
        }    
           
        //build dm.tree      
    })(datamodel);   


我們創建了一個匿名的函數,並立即執行它,由於外部無法引用它內部的變量,
因此在執行完後很快就會被釋放,關鍵是這種機制不會污染全局對象。

2緩存


再來看一個例子,設想我們有一個處理過程很耗時的函數對象,每次調用都會花費很長時間,
那麼我們就需要將計算出來的值存儲起來,當調用這個函數的時候,首先在緩存中查找,如果找不到,則進行計算,
然後更新緩存並返回值,如果找到了,直接返回查找到的值即可。閉包正是可以做到這一點,因爲它不會釋放外部的引用,
從而函數內部的值可以得以保留。

    var CachedSearchBox = (function(){    
        var cache = {},    
           count = [];    
        return {    
           attachSearchBox : function(dsid){    
               if(dsid in cache){//如果結果在緩存中    
                  return cache[dsid];//直接返回緩存中的對象    
               }    
               var fsb = new uikit.webctrl.SearchBox(dsid);//新建    
               cache[dsid] = fsb;//更新緩存    
               if(count.length > 100){//保正緩存的大小<=100    
                  delete cache[count.shift()];    
               }    
               return fsb;          
           },    
         
           clearSearchBox : function(dsid){    
               if(dsid in cache){    
                  cache[dsid].clearSelection();      
               }    
           }    
        };    
    })();    
         
    CachedSearchBox.attachSearchBox("input1");    


這樣,當我們第二次調用CachedSearchBox.attachSerachBox(“input1”)的時候,
我們就可以從緩存中取道該對象,而不用再去創建一個新的searchbox對象。

3 實現封裝


可以先來看一個關於封裝的例子,在person之外的地方無法訪問其內部的變量,而通過提供閉包的形式來訪問:

    var person = function(){    
        //變量作用域爲函數內部,外部無法訪問    
        var name = "default";       
           
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    }();    
         
    print(person.name);//直接訪問,結果爲undefined    
    print(person.getName());    
    person.setName("abruzzi");    
    print(person.getName());    
       
    得到結果如下:  
       
    undefined  
    default  
    abruzzi  


 

4 閉包的另一個重要用途是實現面向對象中的對象,傳統的對象語言都提供類的模板機制,
這樣不同的對象(類的實例)擁有獨立的成員及狀態,互不干涉。雖然JavaScript中沒有類這樣的機制,但是通過使用閉包,
我們可以模擬出這樣的機制。還是以上邊的例子來講:

    function Person(){    
        var name = "default";       
           
        return {    
           getName : function(){    
               return name;    
           },    
           setName : function(newName){    
               name = newName;    
           }    
        }    
    };    
         
         
    var john = Person();    
    print(john.getName());    
    john.setName("john");    
    print(john.getName());    
         
    var jack = Person();    
    print(jack.getName());    
    jack.setName("jack");    
    print(jack.getName());    
       
    運行結果如下:  
       
    default  
    john  
    default  
    jack  


由此代碼可知,john和jack都可以稱爲是Person這個類的實例,因爲這兩個實例對name這個成員的訪問是獨立的,互不影響的。

發佈了24 篇原創文章 · 獲贊 21 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章