官方的解釋是:閉包是一個擁有許多變量和綁定了這些變量的環境的表達式(一般是一個函數),於是這些變量也是該表達式的一部分。javascript
通俗理解:閉包就是可以讀取其餘函數內部變量的函數。java
<h1>wenbin</h1> <script> function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ n = n+2; alert(n); } return f2; } var result=f1(); result(); // 1001 nAdd(); result(); // 1004 </script>
在這段代碼中,result實際上就是閉包f2函數。它一共運行了兩次,第一次的值是1001,第二次的值是1004。這證實了,函數f1中的局部變量n一直保存在內存中,並無在f1調用後被自動清除。安全
爲何會這樣呢?緣由就在於f1是f2的父函數,而f2被賦給了一個全局變量,這致使f2始終在內存中,而f2的存在依賴於f1,所以f1也始終在內存中,不會在調用結束後,被垃圾回收機制(garbage collection)回收。閉包
這段代碼中另外一個值得注意的地方,就是「nAdd=function(){n+=1}」這一行,首先在nAdd前面沒有使用var關鍵字,所以 nAdd是一個全局變量,而不是局部變量。其次,nAdd的值是一個匿名函數(anonymous function),而這個函數
匿名函數自己也是一個閉包,因此nAdd至關因而一個setter,能夠在函數外部對函數內部的局部變量進行操做。性能
當函數f1的內部函數f2被函數f1外的一個變量result引用的時候,就建立了一個閉包。this
閉包的做用:簡而言之,閉包的做用就是在f1執行完並返回後,閉包使得Javascript的垃圾回收機制GC不會收回f1所佔用的資源,由於f1的內部函數f2的執行須要依賴f1中的變量。對象
閉包的應用場景
保護函數內的變量安全。以最開始的例子爲例,函數a中i只有函數b才能訪問,而沒法經過其餘途徑訪問到,所以保護了i的安全性。blog
1 在內存中維持一個變量。依然如前例,因爲閉包,函數a中i的一直存在於內存中,所以每次執行c(),都會給i自加1。ip
2 經過保護變量的安全實現JS私有屬性和私有方法(不能被外部訪問),私有屬性和方法在Constructor外是沒法被訪問的
function Constructor(...) { var that = this; var membername = value; function membername(...) {...} }
使用閉包的注意點
1 因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。
2 閉包會在父函數外部,改變父函數內部變量的值。因此,若是你把父函數看成對象(object)使用,把閉包看成它的公用方法(Public Method),把內部變量看成它的私有屬性(private value),這時必定要當心,不要隨便改變父函數內部變量的值。