У вас очень распространенная проблема закрытия в цикле for
.
Переменные, заключенные в замкнутый цикл, имеют общее единое окружение, поэтому к моменту выполнения обратного вызова onclick
цикл уже завершился, и переменная i
будет указывать на последнюю запись.
Вы можете решить эту проблему с помощью еще большего количества замыканий, используя фабрику функций:
function makeOnClickCallback(i) {
return function() {
alert(i);
return false;
};
}
var i;
for (i = 0; i < 2; i++) {
buttons[i].onclick = makeOnClickCallback(i);
}
Это может быть довольно сложной темой, если вы не знакомы с тем, как работают замыкания. Вы можете ознакомиться со следующей статьей Mozilla для краткого введения:
Примечание: Я бы также посоветовал не использовать var
внутри цикла for
, потому что это может обмануть вас, заставив поверить, что переменная i
имеет область видимости блока, в то время как переменная i
, как и buttons
, имеет область видимости внутри функции.
Вам нужно сохранить состояние переменной i
, потому что к моменту срабатывания события скопированное состояние i
увеличилось до максимального количества циклов.
window.onload = function () {
var buttons = document.getElementsByTagName('a');
for (var i=0; i<2; i++) {
(function (i) {
buttons[i].onclick = function () {
alert(i);
return false;
}
})(i);
}
}
В приведенном выше примере создается анонимная функция с единственным аргументом i
, которая затем вызывается с передачей i
в качестве этого аргумента. При этом создается новая переменная в отдельной области видимости, сохраняя значение в том виде, в котором оно было во время данной конкретной итерации.
Это проблема порядка выполнения
Как назначить обратные вызовы событий итерации массива в javascript (jQuery)
По сути, обработчик клика обращается к i
уже после выхода из цикла, и поэтому i
равен 2
.