Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #31 (permalink)  
Старый 19.06.2017, 11:26
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

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

Последний раз редактировалось Alessio18911, 19.06.2017 в 11:52.
Ответить с цитированием
  #32 (permalink)  
Старый 19.06.2017, 12:00
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,077

Alessio18911,
одна переменная на все клики, почему переменная должна показывать, не то что есть на данный момент?нужно сохранить значение на момент создания функции, тогда нужно замыкание.
Ответить с цитированием
  #33 (permalink)  
Старый 19.06.2017, 12:10
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 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 будут присваиваться последовательно, по мере работы цикла, а функции - только последнее, т.к. это функция и она вложена в цикл?
Ответить с цитированием
  #34 (permalink)  
Старый 19.06.2017, 12:25
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,077

Alessio18911,
возможно кто-то пояснит лучше ...
Ответить с цитированием
  #35 (permalink)  
Старый 19.06.2017, 12:31
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Не обижайтесь, дело во мне.
Ответить с цитированием
  #36 (permalink)  
Старый 19.06.2017, 13:12
Профессор
Отправить личное сообщение для Dilettante_Pro Посмотреть профиль Найти все сообщения от Dilettante_Pro
 
Регистрация: 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.
Ответить с цитированием
  #37 (permalink)  
Старый 19.06.2017, 13:35
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,661

Alessio18911, после выполнения цикла в i останется последнее значение, обработчик выполняется не в цикле (там он просто инициируется на элементе) и не сразу после цикла, а когда-то в будущем когда пользователь кликнет на элемент. Такой код который выполняется не синхронно по ходу, а на наступление какого-то события в будущем называется асинхронным, например, к такому коду относятся все обработчики событий addEventListener и его свойство-атрибутные аналоги (выполняется на наступление события), setTimeout и setInterval (на окончание задержки), requestAnimationFrame (на перерисовку кадра), XMLHttpRequest и fetch (на ответ сервера), Promise (обертка для удобной организации асинхронного кода), возможно еще что-то забыл. Используя всё это библиотеки и фреймворки строят свои более универсальные и удобные асинхронные методы, например, jquery имеет .on() над addEventListener, .ajax() над XMLHttpRequest и тд.
Ответить с цитированием
  #38 (permalink)  
Старый 19.06.2017, 19:12
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Здравствуйте, 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:14.
Ответить с цитированием
  #39 (permalink)  
Старый 19.06.2017, 19:19
Аспирант
Отправить личное сообщение для Alessio18911 Посмотреть профиль Найти все сообщения от Alessio18911
 
Регистрация: 18.06.2017
Сообщений: 87

Добрый день, Rise! Только сегодня расплавившийся мозг вдруг выдал какую-то туманную идею, что, наверное, дело в том, как выполняется цикл с обработчиком. К обеду он приобрёл более-менее ясные очертания, а Ваше сообщение окончательно подтвердило мои раздумья. Возможно, я ещё не дошёл до тех глав учебника, где говорится про возможность НЕсинхронного выполнения цикла.. Но в самом начале - всё время идут примеры с последовательным выполнением строк за одну итерацию. И в главе про функции не говорится, что некоторые функции имеют такие особенности. Вот это незнание возможности асинхронности цикла и привело к загвоздке, которая разрешилась в результате совместных усилий. За что и благодарю и Вас, что уделили мне время.
Ответить с цитированием
  #40 (permalink)  
Старый 19.06.2017, 19:31
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,661

Alessio18911, но я не писал про асинхронности цикла это ты сам сочинил)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как передать данные из json в названия параметров shultz1988 Общие вопросы Javascript 2 20.07.2011 11:15
Уникальность элементов в массиве - как? .andreev Общие вопросы Javascript 2 14.11.2010 15:03
Получение данных из тега в массиве, как? Madd Общие вопросы Javascript 37 06.07.2010 00:59
Как определить количество элементов в многомерном массиве Dima00782 Общие вопросы Javascript 3 12.06.2010 14:15
Как найти индекс по элементу в двумерном массиве? bayah Общие вопросы Javascript 5 22.04.2010 16:26