常常被問到什麼是閉包?javascript
說實話閉包這個概念很難解釋。JavaScript權威指南里有這麼一段話:「JavaScript函數是將要執行的代碼以及執行這些代碼做用域構成的一個綜合體。在計算機學術語裏,這種代碼和做用域額綜合體叫作閉包。」。言外之意全部的JavaScript函數都是閉包。css
有人會說,這個解釋不對。咱們常常說的閉包應該像下面的一串代碼:html
var f1 = function(){ var a=1; return function f2(){ a++; alert(a) } } var b = f1(); b(); // 2 b(); // 3
是的,這是閉包中的一個經典例子,也是咱們一般說的閉包。在這段代碼中,b即是閉包f2的函數。java
爲何使用閉包?web
寫到這裏,咱們不得不先理解下JavaScript的特殊變量做用域和JavaScript的垃圾回收機制了。閉包
(1)、什麼是變量做用域呢?一個變量的做用域是程序中第一這個變量的區域。JavaScript的變量分爲「全局變量」和「局部變量」。函數
全局變量:全局變量的做用域是全局性的,即在JavaScript代碼中,它到處都有定義。我常常寫一個「a=1」,這個變量「a」就被定義成了全局性的了。性能
局部變量:在函數以內聲明的變量,就只在函數體內部定義,它的做用域是局部性的。函數的參數也是局部變量,它們只在函數體內有定義。在函數體內,局部變量的優先級比同名的全局變量要高,例如:學習
var a =1; function f1(){ var a=2; alert(a); } f1(); // 2
那麼若是我把 變量「a」變成局部變量的話,例如:spa
function f1(){ var a=2; } alert(a);
就會報以下圖的錯誤:
有人會說,怎麼 可能會有這麼奇葩的需求,下面我舉個例子,你們就會發現,其實咱們仍是用過的。
閉包實例:
當我「點擊」按鈕時,效果以下:
代碼咱們也許會這麼處理:
$('.button').click(function(){ var length = $('.list').find('li').length; var timer =null; for(var i=0;i<length;i++){ timer=setTimeout(function(){ if(i>length){ clearInterval(timer); } $('.list li').eq(i).css({'-webkit-transform':'scale('+(i+1)+')','marginLeft':(i+1)*50 +'px'}) console.log(i) },i*2000) } })
運行以後你會發現,並無出現咱們想要的效果,打印「i」,發現,,怎麼會輸出了3次「3」呢,實際上是for()裏面的變量i的做用域問題,i的做用域僅在for循環的函數體內,怎麼才能實現這個效果呢,咱們能夠作個小的改動,代碼以下:
$('.button').click(function(){ var length = $('.list').find('li').length; var timer =null; for(var i=0;i<length;i++){ timer=setTimeout((function(i){ if(i>length){ clearInterval(timer); } $('.list li').eq(i).css({'-webkit-transform':'scale('+(i+1)+')','marginLeft':(i+1)*50 +'px'}) //console.log(i) })(i),i*2000) } })
把「i」,當作參數傳進去,這便構成了閉包。
(2)、什麼是JavaScript的垃圾回收機制呢?
答:JavaScript不要求手動的釋放內存,它使用一種稱爲垃圾收集的方法,JavaScript的解釋器能夠檢測到什麼時候程序再也不使用一個對象了。當它肯定了,一個對象是無用的時候,JavaScript的解釋器就把該對象所佔用的內存釋放掉了。
因此綜上所述,就不難理解,在f1函數裏定義一個局部變量a,在f1函數外面,變量a會找不到,由於,它被釋放掉了。
咱們是否是能夠這麼認爲「閉包的做用(或者定義)就是使私有的變量(也能夠理解爲局部變量)可以被多個函數共享,而不被JavaScript的解析器自動的從內存中釋放掉」
閉包的缺點:因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。
樓樓不才,對閉包的理解目前就這麼多,等深刻學習了,會再補充和修正的。推薦你們能夠看看「阮一峯」老師寫的「學習Javascript閉包(Closure)」,連接:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html