對js閉包的理解
閉包的基本理解
閉包是什麼?相信很多初學JS的人一定對這個概念比較模糊,我也是看了很多部落格和書籍才稍微瞭解了一點。因為閉包的應用非常廣泛,在js程式碼裡基本可以說是隨處可見,所以想要學好js,閉包是必須要掌握的。不過在瞭解閉包之前,首先要了解JS的全域性變數,區域性變數和作用域鏈,關於作用域鏈可以參考這篇部落格http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html
在瞭解作用域鏈之後,就開始學習閉包吧
我們在定義區域性變數的時候一定要記得var命令,如果沒有這個,宣告出來的變數就是全域性變數。
function f1(){
n=1;
}
alert(n); // 1
上面程式碼等同於
var n=1;
function f1(){
}
alert(n); // 1
因為js的函式內部可以直接訪問到外部的變數
var n=1;
function f1(){
alert(n); // 1
}
外部就不能訪問內部的變數
function f1(){
var n=1;
}
alert(n); // error
閉包就是能使外部訪問其他函式內部的函式,舉一個閉包的簡單例子吧
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c(); // 1
這段程式碼有兩個特點:
1、函式b巢狀在函式a內部;
2、函式a返回函式b;
這樣在執行完var c=a()後,變數c實際上是指向了函式b,再執行c()後就會彈出一個視窗顯示i的值(第一次為1)。這段程式碼其實就建立了一個閉包,為什麼?因為函式a外的變數c引用了函式a內的函式b,就是說:
當函式a的內部函式b被函式a外的一個變數引用的時候,就建立了一個閉包。
簡而言之,閉包的作用就是在a執行完並返回後,閉包使得Javascript的垃圾回收機制GC不會收回a所佔用的資源,因為a的內部函式b的執行需要依賴a中的變數。
在上面的例子中,由於閉包的存在使得函式a返回後,a中的i始終存在,這樣每次執行c(),i都是自加1後alert出i的值。
用閉包可以解決很多問題,如
function a(){
var result = new Array();
for(var i=0;i<10;i++)
{
result[i]=function(){
return i;
}
}
return result;
}
這個函式會返回一個函式陣列,表面上看每個函式都應該返回自己索引值,也就是位置0的時候返回0,1的時候返回1。但實際上每個函式都返回的是10,因為每個函式的作用域鏈裡都儲存這a()函式的活動物件,所以他們引用的都是同一個變數i,當函式a()返回後,i的值為10,此時每個函式都儲存這同一個變數i,所以每個函式內部i的值都是10,用閉包的解決方法如下:
function a(){
var result = new Array();
for(var i=0;i<10;i++)
{
result[i]=(function(i){
return function(){
return i;
};
})(i);
}
return result;
}