Проблема в том, что вы "закрываете" над одной и той же переменной.
var не объявляет переменную1. Она просто указывает на 'остановку поиска' идентификатора в данном контексте выполнения.
Пожалуйста, смотрите Javascript Closures "FAQ Notes" для всех приятных деталей. Наиболее интересны разделы о "контексте выполнения" и "цепочке областей видимости".
Распространенной идиомой является выполнение двойной привязки для создания нового контекста выполнения.
Например,
var k
for (k = 1; k < 10; k++) {
setTimeout((function (_k) {
return function () {
alert(_k)
}
})(k), k * 100)
}
Начиная с JavaScript 5th Edition существует Function.bind
(она может быть реализована и в 3rd edition, например, bind from prototype.js), которую можно использовать следующим образом:
var k
for (k = 1; k < 10; k++) {
setTimeout((function () {
alert(this)
}).bind(k), k * 100)
}
1 Эта конструкция называется в спецификации ECMAScript объявлением переменных. Однако, это утверждение, как бы оно не вводило в заблуждение, подчеркивается для того, чтобы донести до читателя определенную мысль: также см. "поднятие переменной".