![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 11:26
|
Аспирант
|
|
Регистрация: 18.06.2017
Сообщений: 87
|
|
Так а почему финальное? Ведь цикл выполняется последовательно, а это событие onclick лежит ВНУТРИ него! ![Unsure](https://javascript.ru/forum/images/smilies/unsure.gif)
Последний раз редактировалось Alessio18911, 19.06.2017 в 11:52.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 12:00
|
![Аватар для рони](https://javascript.ru/forum/image.php?u=7416&dateline=1372796129) |
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,077
|
|
Alessio18911,
одна переменная на все клики, почему переменная должна показывать, не то что есть на данный момент?нужно сохранить значение на момент создания функции, тогда нужно замыкание.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 12:10
|
Аспирант
|
|
Регистрация: 18.06.2017
Сообщений: 87
|
|
Простите, возможно, Вам кажется очень простым этот вопрос, но для меня непонятно. Да, я понял, что на момент создания функции переменная должна показывать то, что в ней есть. Да, она одна на все клики, согласен. Но ведь onclick в цикле! Т.е. - возьмём мой ошибочный пример:
for (var i = 0; i < label.length; i++)
{
label[i].addEventListener('click', function() {
page.className = "page bg" + (i+1);
});
}
Получается, что - с учётом порядка действий при обработке кода - сначала выполнится цикл - т.е. i получит своё финальное значение. Затем будет выполняться функция add.EventListener и, соответственно, (i+1) получит сразу значение финального i + 1, т.е. 4. Так? Т.е. label[i], поскольку это массив, i будут присваиваться последовательно, по мере работы цикла, а функции - только последнее, т.к. это функция и она вложена в цикл?
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 12:25
|
![Аватар для рони](https://javascript.ru/forum/image.php?u=7416&dateline=1372796129) |
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,077
|
|
Alessio18911,
возможно кто-то пояснит лучше ...
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 12:31
|
Аспирант
|
|
Регистрация: 18.06.2017
Сообщений: 87
|
|
Не обижайтесь, дело во мне.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 13:12
|
Профессор
|
|
Регистрация: 27.11.2015
Сообщений: 2,899
|
|
Alessio18911,
Попробую объяснить.
Ваш пример
for (var i = 0; i < label.length; i++)
{
label[i].addEventListener('click', function() {
page.className = "page bg" + (i+1);
});
}
Здесь цикл по i - это создание обработчиков события click для всех элементов массива label.
строка
page.className = "page bg" + (i+1);
при этом не исполняется - просто запоминается в конкретном обработчике (причем запоминается идентификатор i, а не его значение).
По завершении цикла создания обработчиков i принимает финальное значение - и больше не меняется.
При исполнении по событию click обработчика для любого элемента из списка label выполнится вышеуказанная строка, в которой будет использоваться это значение
Иллюстрация:
Вариант с использованием значения i при создании обработчика
<div style="border:1px solid black">1</div>
<div style="border:1px solid black">2</div>
<div style="border:1px solid black">3</div>
<div style="border:1px solid black">4</div>
<script>
var divs = document.querySelectorAll('div');
for(var i = 0; i < divs.length; i++) {
divs[i].onclick = function(x)
{
return function()
{
alert(x)
}
}(i);
}
</script>
Вариант с использованием идентификатора i при создании обработчика
<div style="border:1px solid black">1</div>
<div style="border:1px solid black">2</div>
<div style="border:1px solid black">3</div>
<div style="border:1px solid black">4</div>
<script>
var divs = document.querySelectorAll('div');
for(var i = 0; i < divs.length; i++) {
divs[i].onclick = function()
{
alert(i)
};
}
</script>
Последний раз редактировалось Dilettante_Pro, 19.06.2017 в 13:57.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 13:35
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,661
|
|
Alessio18911, после выполнения цикла в i останется последнее значение, обработчик выполняется не в цикле (там он просто инициируется на элементе) и не сразу после цикла, а когда-то в будущем когда пользователь кликнет на элемент. Такой код который выполняется не синхронно по ходу, а на наступление какого-то события в будущем называется асинхронным, например, к такому коду относятся все обработчики событий addEventListener и его свойство-атрибутные аналоги (выполняется на наступление события), setTimeout и setInterval (на окончание задержки), requestAnimationFrame (на перерисовку кадра), XMLHttpRequest и fetch (на ответ сервера), Promise (обертка для удобной организации асинхронного кода), возможно еще что-то забыл. Используя всё это библиотеки и фреймворки строят свои более универсальные и удобные асинхронные методы, например, jquery имеет .on() над addEventListener, .ajax() над XMLHttpRequest и тд.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 19:12
|
Аспирант
|
|
Регистрация: 18.06.2017
Сообщений: 87
|
|
Здравствуйте, Dilettante_Pro! Спасибо, что не прошли мимо. ![](https://javascript.ru/forum/images/smilies/smile.gif) Перескажу, что я понял, своими словами.
Итак, в моём неправильном примере функция, которая вложена в addEventListener не может быть выполнена в процессе выполнения цикла, т.к. в коде нигде не прописан запуск её программным кодом, зато написано, что только человек - клацнув мышью - это сделает. Поэтому цикл выполняется и результат его работы - у каждого элемента массива привешен ОДИН И ТОТ же обработчик с выражением page.className = "page bg" + (i+1); При этом это выражение не высчитывалось, поскольку функция была "мёртвой". Цикл закончился, i дошло по финала, стало 2 (у меня 3 элемента в массиве) и "застыло навеки". Когда человек клацнул на какой-либо элемент массива, только это "оживило" функцию и она стала искать i, найдя его только ЗА своими пределами, т.е. у цикла, который, однако, уже отработал. Теперь, независимо от того, какой элемент массива будет кликнут, одно и то же i приведёт к вычислению одного и того же результата, поэтому чуда не произойдёт.
Берём правильный вариант. Для того, чтобы он был правильный, нужно заставить функцию работать при каждой итерации цикла. Для этого остаётся "оболочка" addEventListener, которая так и будет ждать клика от человека, а вот внутри неё - "живая" функция, которую принудительно будет оживлять вызов с (i) после её же закрытой фигурной скобки. В результате каждой итерации цикла выражение page.className = "page bg" + (i+1); будет высчитываться, и по окончании работы цикла у каждого элемента массива будет не просто обработчик с формулой, а "индивидуализированный" с готовым значением page.className. И клац мышью по любому элементу приведёт просто уже к присвоению соответствующего класса элементу.
Правильно понял? ![Unsure](https://javascript.ru/forum/images/smilies/unsure.gif)
Последний раз редактировалось Alessio18911, 19.06.2017 в 19:14.
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 19:19
|
Аспирант
|
|
Регистрация: 18.06.2017
Сообщений: 87
|
|
Добрый день, Rise! Только сегодня расплавившийся мозг вдруг выдал какую-то туманную идею, что, наверное, дело в том, как выполняется цикл с обработчиком. К обеду он приобрёл более-менее ясные очертания, а Ваше сообщение окончательно подтвердило мои раздумья. Возможно, я ещё не дошёл до тех глав учебника, где говорится про возможность НЕсинхронного выполнения цикла.. Но в самом начале - всё время идут примеры с последовательным выполнением строк за одну итерацию. И в главе про функции не говорится, что некоторые функции имеют такие особенности. Вот это незнание возможности асинхронности цикла и привело к загвоздке, которая разрешилась в результате совместных усилий. За что и благодарю и Вас, что уделили мне время. ![](https://javascript.ru/forum/images/smilies/smile.gif)
|
|
![Старый](/forum/images/ca_serenity/statusicon/post_old.gif)
19.06.2017, 19:31
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,661
|
|
Alessio18911, но я не писал про асинхронности цикла это ты сам сочинил)
|
|
|
|