Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   как сократить названия классов с общим началом в массиве (https://javascript.ru/forum/misc/69381-kak-sokratit-nazvaniya-klassov-s-obshhim-nachalom-v-massive.html)

Alessio18911 19.06.2017 11:26

Так а почему финальное? Ведь цикл выполняется последовательно, а это событие onclick лежит ВНУТРИ него!:-?

рони 19.06.2017 12:00

Alessio18911,
одна переменная на все клики, почему переменная должна показывать, не то что есть на данный момент?нужно сохранить значение на момент создания функции, тогда нужно замыкание.

Alessio18911 19.06.2017 12:10

Простите, возможно, Вам кажется очень простым этот вопрос, но для меня непонятно. Да, я понял, что на момент создания функции переменная должна показывать то, что в ней есть. Да, она одна на все клики, согласен. Но ведь 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 будут присваиваться последовательно, по мере работы цикла, а функции - только последнее, т.к. это функция и она вложена в цикл?

рони 19.06.2017 12:25

Alessio18911,
возможно кто-то пояснит лучше ...

Alessio18911 19.06.2017 12:31

Не обижайтесь, дело во мне.

Dilettante_Pro 19.06.2017 13:12

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>

Alessio18911 19.06.2017 19:12

Здравствуйте, Dilettante_Pro! Спасибо, что не прошли мимо. :) Перескажу, что я понял, своими словами.
Итак, в моём неправильном примере функция, которая вложена в addEventListener не может быть выполнена в процессе выполнения цикла, т.к. в коде нигде не прописан запуск её программным кодом, зато написано, что только человек - клацнув мышью - это сделает. Поэтому цикл выполняется и результат его работы - у каждого элемента массива привешен ОДИН И ТОТ же обработчик с выражением page.className = "page bg" + (i+1); При этом это выражение не высчитывалось, поскольку функция была "мёртвой". Цикл закончился, i дошло по финала, стало 2 (у меня 3 элемента в массиве) и "застыло навеки". Когда человек клацнул на какой-либо элемент массива, только это "оживило" функцию и она стала искать i, найдя его только ЗА своими пределами, т.е. у цикла, который, однако, уже отработал. Теперь, независимо от того, какой элемент массива будет кликнут, одно и то же i приведёт к вычислению одного и того же результата, поэтому чуда не произойдёт.

Берём правильный вариант. Для того, чтобы он был правильный, нужно заставить функцию работать при каждой итерации цикла. Для этого остаётся "оболочка" addEventListener, которая так и будет ждать клика от человека, а вот внутри неё - "живая" функция, которую принудительно будет оживлять вызов с (i) после её же закрытой фигурной скобки. В результате каждой итерации цикла выражение page.className = "page bg" + (i+1); будет высчитываться, и по окончании работы цикла у каждого элемента массива будет не просто обработчик с формулой, а "индивидуализированный" с готовым значением page.className. И клац мышью по любому элементу приведёт просто уже к присвоению соответствующего класса элементу.

Правильно понял?:-?

Alessio18911 19.06.2017 19:19

Добрый день, Rise! Только сегодня расплавившийся мозг вдруг выдал какую-то туманную идею, что, наверное, дело в том, как выполняется цикл с обработчиком. К обеду он приобрёл более-менее ясные очертания, а Ваше сообщение окончательно подтвердило мои раздумья. Возможно, я ещё не дошёл до тех глав учебника, где говорится про возможность НЕсинхронного выполнения цикла.. Но в самом начале - всё время идут примеры с последовательным выполнением строк за одну итерацию. И в главе про функции не говорится, что некоторые функции имеют такие особенности. Вот это незнание возможности асинхронности цикла и привело к загвоздке, которая разрешилась в результате совместных усилий. За что и благодарю и Вас, что уделили мне время. :)

Alessio18911 19.06.2017 19:33

Rise, прошу прощения, КОД :) - знАчимое уточнение )

Dilettante_Pro 20.06.2017 12:46

Alessio18911,
Цитата:

Сообщение от Alessio18911
Правильно понял?

Ок


Часовой пояс GMT +3, время: 03:53.