js閉包的用途

咱們來看看閉包的用途。事實上,經過使用閉包,咱們能夠作不少事情。好比模擬面向對象的代碼風格;更優雅,更簡潔的表達出代碼;在某些方面提高代碼的執行效率。web


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緩存函數


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

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 實現封裝spa


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

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中沒有類這樣的機制,可是經過使用閉包,
咱們能夠模擬出這樣的機制。仍是以上邊的例子來說:orm

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這個成員的訪問是獨立的,互不影響的。對象

相關文章
相關標籤/搜索