1. 程式人生 > >javascript閉包問題

javascript閉包問題

方法 col 例子 pos function urn 引用 10個 fun

什麽是閉包??

有權訪問另一個函數作用域內變量的函數就是閉包。

看一個例子:

 1 function a(){
 2   var n = 0;
 3   function inc(){
 4     n++; 
 5     console.log(n);
 6   }
 7   return inc;
 8 }
 9 var c = a();
10 c();  //控制臺輸出1
11 c();  //控制臺輸出2

在這裏,控制臺兩次輸出不一樣???為什麽??變量n不是重新賦值了嗎??

並沒有,在這裏,var c = a(); 這段代碼意思是將 a 方法的返回值賦值給變量 c ,那麽 a() 的返回值就是 inc ,也就 function inc() ,

後面執行兩次 c(); c(); 實際上是執行兩次的 inc(); 因為function一直引用著a(),所以n沒有回收,也就是說,n的值一直在用著,

自然第一次執行 c() 打印1,第二次執行 c() 打印2;

再看一個經典例子:

 1 function createFunctions(){
 2   var result = [];
 3   for (var i=0; i < 10; i++){
 4     result[i] = function(){
 5       return i;
 6     };
 7   }
 8   return result;
 9 }
10 var funcs = createFunctions(); 11 for (var i=0; i < funcs.length; i++){ 12 console.log(funcs[i]()); 13 }

一般來說,以為輸出 0~9 ,但事實上是輸出10個10。

需要註意的點就是,方法帶()才是執行這個方法,而諸如 var abc = function(){ },只能說將這個方法定義並且賦值給abc,並沒有執行這個方法。

簡單來說:單純的一句 var f = function() { alert(‘lalala‘); }; 是不會彈窗的,後面接一句 f(); 才會執行方法內部的代碼,才會彈窗。

以上代碼的解釋:

 1 function createFunctions(){
 2   var result = new Array();
 3   for (var i=0; i < 10; i++){
 4     result[i] = function(){
 5       return i;
 6     };
 7   }
 8   return result;
 9 }
10 var funcs = createFunctions(); //執行了一次createFunctions()
11 for (var i=0; i < funcs.length; i++){
12   console.log(funcs[i]());  //createFunctions的返回值是result,所以funcs[i]() 執行的是 result[i] 的方法:return i;
13 }

執行流程:

 1  var result =[], i;
 2  result[0] = function(){ return i; }; //沒執行函數,函數內部不變,不能將函數內的i替換!這是在將createFunction()賦值給funcs時的第一次執行這個方法
 3  result[1] = function(){ return i; }; //沒執行函數,函數內部不變,不能將函數內的i替換!
 4  ...
 5  result[9] = function(){ return i; }; //沒執行函數,函數內部不變,不能將函數內的i替換!
 6  i = 10;   //此時的i = 10;
 7  funcs = result;  //因為createFuntions()的返回值是result
 8  result = null;
 9    
10  console.log(i); // funcs[0]()就是執行 return i 語句,就是返回10
11  console.log(i); // funcs[1]()就是執行 return i 語句,就是返回10
12  ...
13  console.log(i); // funcs[9]()就是執行 return i 語句,就是返回10

因為正在引用 i ,所以 i 的值是10,也就是 return i ; 的值一直是return 10 。 傳遞到執行 funcs[i]() 方法裏面。

funcs[0]()就是執行 return i 語句,就是返回10
funcs[1]()就是執行 return i 語句,就是返回10
funcs[9]()就是執行 return i 語句,就是返回10

閉包就是一個函數引用另外一個函數的變量,因為變量被引用著所以不會被回收,因此可以用來封裝一個私有變量。這是優點也是缺點,不必要的閉包只會徒增內存消耗!另外使用閉包也要註意變量的值是否符合你的要求,因為他就像一個靜態私有變量一樣。閉包通常會跟很多東西混搭起來,接觸多了才能加深理解,這裏只是開個頭說說基礎性的東西。

javascript閉包問題