標籤:blog class c java tar http
js閉包的用途
我們來看看閉包的用途。事實上,通過使用閉包,我們可以做很多事情。比如類比物件導向的代碼風格;更優雅,更簡潔的表達出代碼;在某些方面提升代碼的執行效率。
1 匿名自執行函數
我們知道所有的變數,如果不加上var關鍵字,則預設的會添加到全域對象的屬性上去,這樣的臨時變數加入全域對象有很多壞處,
比如:別的函數可能誤用這些變數;造成全域對象過於龐大,影響訪問速度(因為變數的取值是需要從原型鏈上遍曆的)。
除了每次使用變數都是用var關鍵字外,我們在實際情況下經常遇到這樣一種情況,即有的函數只需要執行一次,其內部變數無需維護,
比如UI的初始化,那麼我們可以使用閉包:
[javascript] view plaincopyprint?
- 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緩衝
再來看一個例子,設想我們有一個處理過程很耗時的函數對象,每次調用都會花費很長時間,
那麼我們就需要將計算出來的值儲存起來,當調用這個函數的時候,首先在緩衝中尋找,如果找不到,則進行計算,
然後更新緩衝並傳回值,如果找到了,直接返回尋找到的值即可。閉包正是可以做到這一點,因為它不會釋放外部的引用,
從而函數內部的值可以得以保留。
[javascript] view plaincopyprint?
- 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之外的地方無法訪問其內部的變數,而通過提供閉包的形式來訪問:
[javascript] view plaincopyprint?
- 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中沒有類這樣的機制,但是通過使用閉包,
我們可以類比出這樣的機制。還是以上邊的例子來講:
[javascript] view plaincopyprint?
- 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這個成員的訪問是獨立的,互不影響的。