2013-10-24 36 views
0

在處理nodejs編程時,我發現了一個簡單而有趣的問題。
要依次執行一組異步函數,我通常在async.series中使用'job list array'。

通過以下步驟:

1.定義的陣列
2.按工作職能成陣列。
3.使用async.series,按順序執行。
例如async.series(jobFunctionList,callback);
JavaScript Closure - 將匿名函數的奇怪參考特性推送到數組

下面的示例代碼是簡化的代碼。
在評論中描述,它不工作,如我所料。

即使在定義了Job函數並將其推入jobList數組後,變量'key'和'value'也會改變


似乎推送的函數不斷地引用外部變量,
不是創建的情況的值。


我找到了解決此問題的解決方案,但不知道爲什麼它的工作原理如此。

var dataList = { key1: 'value1', key2: 'value2' }; 

var jobList = new Array(); 

for (var key in dataList) 
{ 
    var value = dataList[key]; 

    jobList.push(
     function (next) 
     { 
      console.log(key + ' : ' + value); 
     } 
    ); 
} 

(jobList[0])(); 
(jobList[1])(); 

/* Expected Output : 

key1 : value1 
key2 : value2 

*/ 

/* Real Output : 

key2 : value2 <--- WHY ??? 
key2 : value2 

*/ 

回答

2

匿名函數使用(共享)來自外部作用域的相同鍵和值變量。當for結束時,它們使用的值是key2 value2,而不是函數定義時的值。

for (var key in dataList) // definition of key 
{ 
    var value = dataList[key]; // definition of value 

    jobList.push(
     function (next) 
     { 
      console.log(key + ' : ' + value); // uses key and value from the outer scope 
     } 
    ); 
} 

(jobList[0])(); // key and value are key2 value2 after for, so they are printed 
(jobList[1])(); // same 

的解決方案是創建一個封蓋,其鍵和值是本地:

for (var key in dataList) // definition of key 
{ 
    var value = dataList[key]; // definition of value 

    jobList.push(
     function(k,v){ // k,v local copies of key and value 
     return function (next) 
      { 
      console.log(k + ' : ' + v); // uses local copies, created one for each iteration 
      } 
     }(key,value); // immediately execute the outer anonymous function, it just creates a local scope 
    ); 
} 
2

由於Teemu表示,其因爲for循環結束的時候,值已經改變

你需要做的是以下幾點:

var dataList = { key1: 'value1', key2: 'value2' }; 

var jobList = new Array(); 

for (var key in dataList) 
{ 
    var value = dataList[key]; 

    jobList.push(
     (function(savedKey, savedValue) { 
      return function (next) { 
       console.log(savedKey + ' : ' + savedValue); 
      } 
     })(key, value) 
    ); 
} 

(jobList[0])(); 
(jobList[1])(); 

雖然savedKeysavedValue可稱爲keyvalue,它會指新的一個,它可能會更有意義讀取它