Для исправления с минимальным воздействием замените строку Event.observe
на следующую:
Event.observe(newDiv, 'click', loadItem.curry(itemID));
Пояснение:
В исходном коде создаваемые вами обработчики событий закрывают (имеют постоянную ссылку) переменную itemID
и поэтому будут использовать значение этой переменной в момент, когда Обработчик события называется , а не тогда, когда вы назначаете его для события. Это значение будет последним значением, которое itemID
имеет в цикле & mdash; для всех функций обработчика. Подробнее о замыканиях здесь.
В пересмотренном коде с минимальным воздействием мы используем функцию curry
Prototype, которая создаст для вас функцию, которая при вызове будет вызывать базовую функцию с аргументами, которые вы дали curry
, (Имя из математики ; Хаскелл Карри придумал эту технику, хотя есть аргументы, что он был не первым, кто это сделал.) Мы могли бы сделать то же самое сами:
items = transport.responseText.evalJSON(); // my list of objects that contains all the details I'll need for that page
for (var itemID in items)
{
newDiv = ... // Creating my div with main infos
$('myDiv').appendChild(newDiv);
// More code to make everything look pretty and that works fine
Event.observe(newDiv, 'click', prepLoadItem(itemID));
}
function prepLoadItem(id) {
return function() {
loadItem(id);
};
}
... но поскольку у Prototype есть функция общего назначения, нам не нужно.
Не по теме : items
это массив? Если нет, игнорируйте этот не по теме комментарий. Если это так, не не используйте for..in
для его обхода или, по крайней мере, если вы не примете некоторые меры предосторожности, приведенный выше код не сделает это должным образом. Подробности здесь , но for..in
- это , а не для циклического перемещения по индексам массива; это для просмотра свойств объекта. Объекты массива вполне могут иметь свойства, отличные от индексов массива (и фактически, если вы используете Prototype, они имеют.)