2015-01-12 59 views
0

我正在嘗試爲第三方控件建立一個處理程序數組。其中一個必需的對象是一個回調處理程序。問題是allProvider(item)被調用,「theValue」變量不再指向相同的位置 - 它總是被設置爲它分配給的最後一個值。我真正想做的是在構建數組時立即評估「theValue.name」,而不是稍後。在這一點上,我願意接受任何解決方案。由於建立一個匿名函數時,預先估計對象值

var handlers = []; 
for(var i=0;i<myArray.length;i++){ 
    var theValue = myArray[i]; 
    handlers.push({ 
     name: myArray.name, 
     allProvider: function(item){ 
      return "All "+ theValue.name; //This always == myArray[myArray.length - 1] 
     } 
    }); 
} 

回答

1

你有一個封閉那裏 - theValue是父作用域的變量的引用,並通過執行該功能它指向的最後一個值就被分配到了時間。

You need to break the closure。常見的模式是使用IIFE。

allProvider: (function(theValue) { 
       return function(item) { 
       return "All "+ theValue.name; 
       } 
      })(theValue) 
+0

那完美。你得到的是第一個和這篇文章的檢查 - 正是我所需要的。謝謝 –

1

亞歷克斯是正確的,解決這個封閉問題的一種可能的方式是嘗試這樣的:

var handlers = []; 

myArray.forEach(function (theValue) { 
    handlers.push({ 
     name: myArray.name, 
     allProvider: function(item){ 
      return "All "+ theValue.name; 
     } 
    }); 
}); 

裏面每個稱爲forEach方法中的匿名功能,theValue將始終指向你所期望的。

編輯:我沒有想到比你有什麼更有效率的東西,只是有用的東西。 map肯定是打二鳥一石,這樣來講話,所以你也可以試試這個:

var handlers = myArray.map(function (theValue) { 
    return { 
     name: myArray.name, 
     allProvider: function(item){ 
      return "All "+ theValue.name; 
     } 
    }; 
}); 

最後,你可以試試這個,如果你不想要的東西,可以在舊的瀏覽器可能會破壞不支持forEachmap

var handlers = [], 
    i; 

for(i = 0; i < myArray.length; i++) { 
    (function (theValue) { 
     handlers.push({ 
      name: myArray.name, 
      allProvider: function(item){ 
       return "All "+ theValue.name; 
      } 
     }); 
    }(myArray[i])); 
} 
1

的問題是回調函數被調用時,for循環結束,所以在通話時間theValue指的是最後一個元素的數組。

我會建議你使用本地陣列地圖功能,爲您的工作像波紋管: -

var handlers = myArray.map(function(theValue) { 
    return { 
     name: myArray.name, 
     allProvider: function(item) { 
      return "All " + theValue.name; 
     } 
    }; 
}); 

BTW IE8不支持地圖功能。

如果你想支持IE8,並降低你能做些什麼,在陣列中的每個元素綁定到像波紋管的功能。

var getObject = function(arrName, valueName) { 
    return { 
     name: arrName, 
     allProvider: function(item) { 
      return "All " + valueName; 
     } 
    } 
} 

var handlers = []; 
for (var i = 0; i < myArray.length; i++) { 
    var theValue = myArray[i]; 
    handlers.push(getObject(myArray.name,theValue.name)); 
}