- 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 выдавал те числа, которые были указаны ему при задании обработчика?
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-шками и на них попробовал.
-
- 1
Такое поведение объясняется тем, что переменная i является глобальной в этом контексте. Этого можно избежать используя замыкание.
function createHandler(n) { return function(event) { window.alert(n); return false; }; // обработчик }и далее в цикле можно использовать
.bind('click', createHandler(i))