感謝大神~!不是原博...數組
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = i; } return arr; } alert(box()) //正常狀況不須要閉包,就能夠達到預期效果,輸出結果爲一個數組0,1,2,3,4
有時咱們須要在for循環裏面添加一個匿名函數來實現更多功能,看下面代碼閉包
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = function(){ return i; //因爲這個閉包的關係,他是循環完畢以後才返回,最終結果是4++是5 } //這個匿名函數裏面根本沒有i這個變量,因此匿名函數會從父級函數中去找i, } //當找到這個i的時候,for循環已經循環完畢了,因此最終會返回5 return arr; } //alert(box()); //執行5次匿名函數自己 //alert(box()[1]); //執行第2個匿名函數自己 //alert(box().length); //最終返回的是一個數組,數組的長度爲5 alert(box()[0]()); //數組中的第一個數返回的是5,這是爲何?
上面這段代碼就造成了一個閉包:函數
閉包是指有權訪問另外一個函數做用域中的變量的函數,建立閉包的常見的方式,就是在一個函數內部建立另外一個函數,經過另外一個函數訪問這個函數的局部變量。post
在for循環裏面的匿名函數執行 return i 語句的時候,因爲匿名函數裏面沒有i這個變量,因此這個i他要從父級函數中尋找i,而父級函數中的i在for循環中,當找到這個i的時候,是for循環完畢的i,也就是5,因此這個box獲得的是一個數組[5,5,5,5,5]。spa
解決方案1code
在看解決方案一以前,咱們先看一下匿名函數的自我執行:blog
匿名函數自我執行的寫法是,在函數體外面加一對圓括號,造成一個表達式,在圓括號後面再加一個圓括號,裏面可傳入參數。ip
例以下代碼:作用域
(function(){ alert('lee'); //匿名函數自我執行(匿名函數)() })();
咱們再來看解決方案1:it
function box(){ var arr = []; for(var i=0;i<5;i++){ arr[i] = (function(num){ //自我執行,並傳參(將匿名函數造成一個表達式)(傳遞一個參數) return num; //這裏的num寫什麼均可以 })(i); //這時候這個括號裏面的i和上面arr[i]的值是同樣的都是取自for循環裏面的i } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[0]);
經過給匿名函數傳參,而傳遞的這個參數i是每次執行for循環裏面的i,每次傳遞的參數i的值都不同,匿名函數裏面的num接收傳遞的參數i,因此box()最終輸出結果爲[0,1,2,3,4]
解決方案2
這種方案的原理就是在匿名函數1裏面再寫入一個匿名函數2,這個匿名函數2須要的num值會在他的父級函數匿名函數1裏面去尋找,而匿名函數1裏面的num值就是傳入的這個參數i,和上面例子中的i是同樣的,
function box(){
var arr = [];
for(var i=0;i<5;i++){
arr[i] = (function(num){
//num在這裏 //原理和上面一種方法同樣的,因此能夠實現閉包
return function(){ //在這個閉包裏面再寫一個匿名函數
return num;
};
})(i)
}
return arr;
}
//alert(box());
//alert(box()[1]);
//alert(box().length);
var b = box();
alert(b[0]());
box()最終返回結果[0,1,2,3,4],
解決方案3
若是將一個匿名函數自我執行的時候賦值給一個變量,那麼這個匿名函數中的圓括號的能夠去掉的,看下面代碼,
var tip = function(){ //這樣把匿名函數自我執行的時候賦值給一個變量,那麼圓括號是能夠去掉的 alert('lee'); }();
利用匿名函數的這一特色,咱們能夠將解決方案1中的代碼改進一下:
var arr = []; for(var i=0;i<5;i++){ arr[i] = function(num){ return num; }(i); } return arr; } //alert(box()); //alert(box()[1]); //alert(box().length); alert(box()[4]);