我有这个回调函数设置:
var contextMenu = [];
var context = [ { "name": "name1", "url": "url1" }, {"name": name2", "url: "url2" } ];
for(var i=0; i < context.length; i++) {
var c = context[i];
var arr = {};
arr[c.name] = function() { callback(c.url); }
contextMenu.push( arr );
}
function callback(url) {
alert(url);
}
问题是传递给回调的url值始终是上下文变量中的最后一个值 - 在本例中为“url2”。我期望将特定值传递给回调的每个“实例”,但由于回调似乎记住了相同的值,因此它最后一次被引用。
我有点卡住了。任何帮助将不胜感激。
PS:我正在使用jQuery ContextMenu,根据我的理解,这不支持将自定义数据发送到其回调函数。正是在这种背景下,我遇到了这个问题。在这种环境下要克服的任何建议也很有帮助!
答案 0 :(得分:16)
使用额外的闭包。
arr[c.name] = (function(url) {
return function() { callback(url); }
})(c.url);
在此主题中查看Creating closures in loops: A common mistake和大多数其他questions,现在您的问题也会添加到此池中。
答案 1 :(得分:3)
您正在for循环中创建一系列闭包函数
arr[c.name] = function() { callback(c.url); }
并且它们都共享相同的范围,因此相同的c
对象将指向循环结束后数组中的最后一个元素。
要解决此问题,请尝试执行以下操作:
arr[c.name] = function(url) {
return function() { callback(url); };
}(c.url);
在此处阅读有关闭包的更多信息:http://jibbering.com/faq/notes/closures/
答案 2 :(得分:0)
我在Creating closures in loops: A common mistake指出Anurag的in his answer上创建了一个通用回调创建器。
//Creates an anonymus function that will call the first parameter of
//this callbackCreator function (the passed callback)
//whose arguments will be this callbackCreator function's remaining parameters
//followed by the arguments passed to the anonymus function
//(the returned callback).
function callbackCreator() {
var functionToCall = arguments[0];
var argumentsOfFunctionToCall = Array.prototype.slice.apply(arguments, [1]);
return function () {
var argumentsOfCallback = Array.prototype.slice.apply(arguments, [0]);
functionToCall.apply(this, argumentsOfFunctionToCall.concat(argumentsOfCallback));
}
}
这是一个自定义AJAX配置对象,其成功回调使用我的回调创建者帮助程序。使用响应文本,回调根据操作发生的行更新DataTables表中行的第一个单元格,并打印消息。
{
url: 'example.com/data/' + elementId + '/generate-id',
method: 'POST',
successHandler: callbackCreator(function (row, message, response) {//Callback parameters: Values we want to pass followed with the arguments passed through successHandler.
table.cell(row, 0).data(JSON.parse(response).text);
console.log(message);
},
$(this).parents('tr'),//Row value we want to pass for the callback.
actionName + ' was successful'//Message value we want to pass for the callback.
)
}
或者在你的情况下:
arr[c.name] = callbackCreator(function(url) {
callback(url);
},
c.url
);