На странице есть 10 ссылок, нужно привязать обработчик onclick
для каждой ссылки, так что бы при нажатии на нее выводился ее порядковый номер, который присваивается в цикле, решил таким образом
https://jsfiddle.net/0qagg1ek/1/
Решил не с первой попытки, хочу разобраться в деталях как проходил выполнение, я понимаю так:
- на каждой итерации цикла вызывается функция на месте, с параметром текущей итерации
- каждой html ссылке, событию
onclick
присваивается ссылка на функцию обработчик :wink:
- у каждого обработчика свое значение при вызове алерта благодаря инкапсуляции во внешнюю функцию, что создает для каждой переменной
index
свою область видимости
Правильно ли я понимаю работу кода? И хочу услышать(прочитать:laughing:) как вы понимаете тот беспредел в просторах памяти который творит этот js
Это извесная задача. Кстати для неё есть оригинальное решение :smile:. Правда оно не компатибильно с ES5 (strict mode).
https://jsfiddle.net/0qagg1ek/3/
Функция вызывается сразу, чтобы вычислять значение переменной index
. Если не оборачивать в функцию, то на выходе из цикла i
будет равно 10
, а поскольку мы навесили на элемент функцию, которая будет выполнена в будущем, при наступления события click
, переменная i
будет вычислена в значение 10
и алертом будет выводиться ее значение, увеличенное на 1.
Можно другим способом решить, если немного отойти от условия задачи: https://jsfiddle.net/y33hvb5a/1. В этом случае мы будем привязываться к конкретному индексу элемента, который не меняется, в отличие от переменных.
1 лайк
Да этот вариант работает правильно, но суть вопроса направлена на понимание замыканий
Можно сказать, своя область видимости есть у каждого константного значения переменной index. Секрет фокуса тут не в инкапсуляции, а в замыкании. Потому что наша функция должна была бы выглядеть как-то так примерно:
function(index){
function(event){
event.preventDefault();
alert(index + 1);
}
}
Но она так не выглядит, потому что когда она вызывается, никакого index во внешнем мире не существует, а вызывается она из элемента, который был когда-то временно прописан в коллекции linksCollection
, и получил там значение переменной index
, хотя, кажется, там была целая функция.
Но это только так кажется, потому что функция в памяти существует в одном-единственном экземпляре, каждый onclick
получает только ссылку на неё, в которую неявно подмыкается значение переменной index, как будто где-то рядом есть такой волшебный цикл, который в момент нажатия на ссылку чудесно оказывается в нужной итерации, но это мираж, потому что цикл уже отработал и ушёл на пенсию.
Беспредел есть только в голове. А в памяти всё как раз оптимальненько, скорее всего.
2 лайка
Можно переписать Вашу функцию по-другому, если смущает способ решения:
[].slice.call(linksCollection).forEach(function (el, index){
el.onclick = function(event){
event.preventDefault();
alert(index + 1);
};
})