Javascript: передача пользовательских аргументов в функцию обратного вызова - PullRequest
6 голосов
/ 28 февраля 2011

У меня есть эта настройка функции обратного вызова:

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 , который, на мой взгляд, не поддерживает отправку пользовательских данных в его функции обратного вызова.Именно в этом контексте у меня есть эта проблема.Любые предложения по преодолению в этой среде также полезны!

Ответы [ 3 ]

16 голосов
/ 28 февраля 2011

Используйте дополнительное замыкание.

arr[c.name] = (function(url) { 
    return function() { callback(url); }
})(c.url);

См. Создание замыканий в циклах: распространенная ошибка и большинство других вопросов по этой теме, а теперь и ваш вопростакже добавлен в этот пул.

3 голосов
/ 28 февраля 2011

Вы создаете серию функций замыкания внутри цикла 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/

0 голосов
/ 16 февраля 2016

Общее решение

Помощник создателя обратного вызова

Я создал общего создателя обратного вызова вдоль Создание замыканий в циклах: распространенная ошибка , что Anurag указал в своем ответе .

Параметры создателя обратного вызова

  • Первым параметром функции является обратный вызов.
  • Каждый другой параметр будет передан в этот обратный вызов в качестве параметров.

Параметры пройденного обратного вызова

  • Первая часть параметров происходит от аргументов, которые вы передали помощнику создателя обратного вызова (после первого параметра, как я описал ранее).
  • Вторая часть основана на аргументах, которые будут напрямую переданы обратному вызову вызывающей стороной.

Исходный код

//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
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...