本文收集了多本書裏對
JavaScript閉包(Closure)
的解釋,或許會對理解閉包有必定幫助。javascript
var fn = f(); // 將函數f 的返回值賦值給變量fn fn(); // 1 fn(); //2 fn(); //3 function f() { var cnt = 0; return function() { return ++cnt; } } var fn1 = f1(); fn1(); //1 fn1(); //1 function f1(){ var cnt = 0; return ++cnt; }
從表面上來看,閉包是一種具備狀態的函數。或者也能夠將閉包的特徵理解爲,其相關的局部變量在函數調用結束以後將會繼續存在。html
經過實現信息隱藏java
//使用了閉包的模塊 // 在此調用匿名函數 // 因爲匿名函數的返回值是一個函數,因此變量sum 是一個函數 var sum = (function() { // 沒法從函數外部訪問該名稱 // 實際上,這變成了一個私有變量 // 通常來講,在函數被調用以後該名稱就將沒法再被訪問 // 不過因爲是在被返回的匿名函數中,因此仍能夠繼續被使用 var position = { x:2, y:3 }; // 一樣是一個從函數外部沒法被訪問的私有變量 // 將其命名爲sum 也能夠。不過爲了不混淆,這裏採用其餘名稱 function sum_internal(a, b) { return Number(a) + Number(b); } // 只不過是爲了使用上面的兩個名稱而隨意設計的返回值 return function(a, b) { print('x = ', position.x); return sum_internal(a, b); }; } )(); // 調用 sum(3, 4); x = 2 7
在利用函數做用域能夠封裝名稱,以及閉包可使名稱在函數調用結束後依然存在這兩個特性後,信息隱藏得以實現。編程
(function() { 函數體 })();
計數器功能的類設計模式
function counter_class(init) { // 初始值能夠經過參數設定 var cnt = init || 0; // 設置默認參數的習慣作法(參見5.5 節) // 若有必要,可在此聲明私有變量與私有函數 return { // 公有方法 show:function() { print(cnt); }, up:function() { cnt++; return this; }, // return this 在使用方法鏈時很方便 down:function() { cnt--; return this; } }; } // 使用代碼 var counter1 = counter_class(); counter1.show(); 0 counter1.up(); counter1.show(); 1 var counter2 = counter_class(10); counter2.up().up().up().show(); // 方法鏈 13
表達式閉包閉包
JavaScript 有一種自帶的加強功能,稱爲支持函數型程序設計的表達式閉包(Expression closure)。異步
var sum = function(a, b) { return Number(a) + Number(b); } //能夠省略爲 var sum = function(a, b) Number(a) + Number(b);
因爲IE9以前的版本對JScript對象和COM對象使用不一樣的垃圾收集例程,所以閉包在IE的這些版本中會致使一些特殊的問題。具體來講,若是閉包的做用域鏈中保存着一個HTML元素,那麼就意味着該元素將沒法被銷燬。函數
function assignHandler(){ var element = document.getElementById("someElement"); element.onclick = function(){ alert(element.id); }; } //把element變量設置爲null。這樣就可以解除對DOM對象的引用,順利地減小其引用數,確保正常回收其佔用的內存。 function assignHandler(){ var element = document.getElementById("someElement"); var id = element.id; element.onclick = function(){ alert(id); }; element = null; }
延續局部變量的壽命this
//把img變量用閉包封閉起來,便能解決請求丟失的問題 var report = (function(){ var imgs = []; return function( src ){ var img = new Image(); imgs.push( img ); img.src = src; } })();