Хорошо, скажем, вы генерируете меню, скажем, в javascript.
var menuItems = [
{ id: 1, text: 'Home' },
{ id: 2, text: 'About' },
{ id: 3, text: 'Contact' }
];
И вы создаете их в цикле, как это:
for(var i = 0; i < menuItems.length; i++) {
var menuItem = menuItems[i];
var a = document.createElement('a');
a.href = '#';
a.innerHTML = menuItem.text;
// assign onclick listener
myMenu.appendChild(a);
}
Теперь, для слушателя onclick, вы можете попробовать что-то вроде этого:
a.addEventListener('click', function() {
alert( menuItem.id );
}, false);
Но вы обнаружите, что это будет иметь каждую ссылку оповещения «3». Поскольку во время щелчка ваш код onclick выполняется, и значение menuItem
вычисляется до последнего элемента, поскольку это было значение, которое было ему назначено в последний раз при последней итерации цикла for.
Вместо этого вы можете создать новое закрытие для каждой ссылки, используя значение menuItem
, равное на тот момент выполнения
a.addEventListener('click', (function(item) {
return function() {
alert( item.id );
}
})( menuItem ), false);
Так что здесь происходит? На самом деле мы создаем функцию, которая принимает item
, а затем немедленно вызывает эту функцию, передавая menuItem
. Так что функция «обертка» - это не то, что будет выполняться при нажатии на ссылку. Мы выполняем его немедленно и назначаем возвращенную функцию в качестве обработчика щелчков.
В данном случае происходит то, что для каждой итерации функция вызывается с новым значением menuItem
, и возвращается функция, которая имеет доступ к этому значению, что фактически создает новое замыкание.
Надеюсь, что все прояснилось =)