首頁 >web前端 >js教程 >js閉包的用途詳解_基礎知識

js閉包的用途詳解_基礎知識

WBOY
WBOY原創
2016-05-16 16:31:451684瀏覽

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

1 匿名自執行函數

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

複製程式碼 程式碼如下:

var datamodel = {   
    table : [],   
    tree : {}   
};   
    
(function(dm){   
    for(var i = 0; i        var row = dm.table.rows[i];   
       for(var j = 0; j            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){//保留快取的大小               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這個成員的存取是獨立的,互不影響的。

以上便是js閉包的作用了,非常簡單易懂吧,希望對小夥伴們有所幫助

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn