•  
  • 0
  •  
0

Проблема с назначением функции обработчика события в JS (jQuery)

Проблема заключается в следующем.
У меня есть функция, которая в цикле обходит пять тегов area, и каждого задаёт обработчик события "click". Проблема в том, что обработчик содержит параметры (i, k), которые меняются при каждой итерации и в обработчике (внутри цикла) приходится указывать эти переменные. Но, что для меня стало открытием, при создании обработчика, он берёт не конкретное значение i и k, а ссылку на них, и в итоге я получаю 5 обработчиков с одинаковыми параметрами.
Ниже пример, где для наглядности, функцию, вызываемую в обработчике, я заменил на alert(). При click'е на любом area сообщение одно и то же (i = 5).

var k    = Id;
for( var i = 0; i < 5; i++ )
{
    $j( '#area_' + i ).unbind( "click" );
    $j( '#area_' + i )
        .bind( "click", function(event){
            alert( 'i = ' + i + ', k = ' + k );
            return false;
        } )
        .attr( 'alt', aImgs[k][0] );

    k++;
    if( undefined == aImgs[k] )
    {
        k   = 0;
    }
}

Собственно, суть вопроса: как сделать так, чтобы для каждого обработчика alert выдавал те числа, которые были указаны ему при задании обработчика?

JavaScript, jQuery.
спросил 823 дня назад Аватор пользователя KeyKeeper KeyKeeper
34 2
изменил 823 дня назад Аватор пользователя KeyKeeper KeyKeeper
34 2
300

2 ответа:

    •  
    • 1
    •  

    Не стану претендовать на полноту и достоверность, но попробую ответить, как сам понимаю.

    Обработчик действительно не "парсится" и в него не подставляются значения переменных, которые ты указываешь в коде. Тебе надо создать переменные, хранящие значения параметров цикла при каждой итерации. Здесь может помочь такая вещь как "Замыкания". Почитать про них можно тут, например, - http://javascript.ru/basic/closure .

    Не могу тебе предложить вариант с jQuery, так как, к своему стыду, всё ещё до неё не добрался, но с прямыми присвоениями рабочий код будет выглядеть примерно так:

    var i = 0, k = 0;
    var t_input = null;
    
    for (i = 0; i < 5; i++) {
      if (!(t_input = document.getElementById('b_' + i))) {
        continue;
      }
      (function() {
        var t_i = i;
        var t_k = k;
        t_input.onclick = function (e) {
          alert('i = ' + t_i + ', k = ' + t_k);
          return false;
        };
      })();
      k++;
    }
    

    Здесь в цикле создаётся анонимная функция, локальные переменные которой сохраняют значения параметров цикла, а сами, в свою очередь, используются внутри обработчика. И тут же эта функция выполняется, чтобы в локальные переменные записались значения параметров на текущей итерации и заодно к выбранному нами объекту прикрепился наш обработчик события. После чего функция прекращает существование, но обработчик замыкает на себя значения её локальных переменных и использует уже их. Если я, конечно, всё правильно понимаю.

    Да, в примере просто создал 5 кнопок с id-шками и на них попробовал.

    ответил 823 дня назад Аватор пользователя RedHedgehog RedHedgehog
    105 3
    •  
    • 1
    •  

    Такое поведение объясняется тем, что переменная i является глобальной в этом контексте. Этого можно избежать используя замыкание.

    function createHandler(n) {
        return function(event) { window.alert(n); return false; }; // обработчик
    }
    

    и далее в цикле можно использовать

    .bind('click', createHandler(i))
    
    ответил 822 дня назад Аватор пользователя HyperGeek HyperGeek
    50 4
Чтобы написать ответ, вы должны авторизироваться.