我們來看看閉包的用途。事實上,通過使用閉包,我們可以做很多事情。比如模擬面向對象的代碼風格;更優(yōu)雅,更簡潔的表達出代碼;在某些方面提升代碼的執(zhí)行效率。
1 匿名自執(zhí)行函數(shù)
我們知道所有的變量,如果不加上var關鍵字,則默認的會添加到全局對象的屬性上去,這樣的臨時變量加入全局對象有很多壞處,比如:別的函數(shù)可能誤用這些變量;造成全局對象過于龐大,影響訪問速度(因為變量的取值是需要從原型鏈上遍歷的)。除了每次使用變量都是用var關鍵字外,我們在實際情況下經(jīng)常遇到這樣一種情況,即有的函數(shù)只需要執(zhí)行一次,其內(nèi)部變量無需維護,
比如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); 我們創(chuàng)建了一個匿名的函數(shù),并立即執(zhí)行它,由于外部無法引用它內(nèi)部的變量,因此在執(zhí)行完后很快就會被釋放,關鍵是這種機制不會污染全局對象。
2緩存
再來看一個例子,設想我們有一個處理過程很耗時的函數(shù)對象,每次調(diào)用都會花費很長時間,那么我們就需要將計算出來的值存儲起來,當調(diào)用這個函數(shù)的時候,首先在緩存中查找,如果找不到,則進行計算,然后更新緩存并返回值,如果找到了,直接返回查找到的值即可。閉包正是可以做到這一點,因為它不會釋放外部的引用,從而函數(shù)內(nèi)部的值可以得以保留。
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"); 這樣,當我們第二次調(diào)用CachedSearchBox.attachSerachBox(“input1”)的時候,我們就可以從緩存中取道該對象,而不用再去創(chuàng)建一個新的searchbox對象。
3 實現(xiàn)封裝
可以先來看一個關于封裝的例子,在person之外的地方無法訪問其內(nèi)部的變量,而通過提供閉包的形式來訪問:
var person = function(){ //變量作用域為函數(shù)內(nèi)部,外部無法訪問 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 閉包的另一個重要用途是實現(xiàn)面向對象中的對象,傳統(tǒng)的對象語言都提供類的模板機制,這樣不同的對象(類的實例)擁有獨立的成員及狀態(tài),互不干涉。雖然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閉包的作用了,非常簡單易懂吧,希望對小伙伴們有所幫助
新聞熱點
疑難解答