Поясните поведение кода JS

D
На сайте с 28.06.2008
Offline
980
151

Дана задача

Даны дивы, содержащие в атрибуте data-num свой порядковый номер:

<div data-num="1">text</div> <div data-num="2">text</div> <div data-num="3">text</div> <div data-num="4">text</div> <div data-num="5">text</div>

Сделайте так, чтобы по клику на любой из дивов ему в конец записывался его порядковый номер.

Подумал и решил так, все работает

    let div = document.getElementsByTagName('div');
    
   for (let i=0; i< div.length; i++){
       div[i].addEventListener('click', function () {
           div[i].innerHTML =  div[i].innerHTML +  div[i].dataset.num
       });
   }

Но пока соображал написал такой вариант, и вот его поведение мне непонятно. Почему  функция go(i) вызывается каждую итерацию цикла?

По идее я ведь просто создаю "слушатель" который должен срабатывать по клику. А тут идет срабатывание сразу при запуске без клика.

    let div = document.getElementsByTagName('div');

   for (let i=0; i< div.length; i++){
       div[i].addEventListener('click', go(i));
   }
    function go(i) {
        div[i].innerHTML =  div[i].innerHTML +  div[i].dataset.num
    }


ArbNet
На сайте с 27.10.2019
Offline
52
#1
let div = document.getElementsByTagName('div');

   for (let i=0; i< div.length; i++){
       div[i].addEventListener('click', go);
   }
    function go(ev) {
        let div=ev.target;
        div.innerHTML=div.innerHTML+div.dataset.num
    }

Не проверял, но должно работать 😊

Dram :

Почему  функция go(i) вызывается каждую итерацию цикла?

По идее я ведь просто создаю "слушатель" который должен срабатывать по клику.

Очередное доказательство, что учебник JS не читали..

Блажен, кто не стремится сделать лучше: он не рискует быть не понятым.
D
На сайте с 28.06.2008
Offline
980
#2

Я уже сделал рабочий вариант, вопрос не в том.

Мне интересно почему нерабочий вариант работает так как работает. Почему слушатель вызывает функцию, хотя клика нет?

T7
На сайте с 19.09.2018
Offline
34
#3
Dram #:
Мне интересно почему нерабочий вариант работает так как работает

Вы напрямую вызвали функцию

go(i)

,  она и отработала.  Все штатно.  addEventListener вторым аргументом ждет функцию обратного вызова с 1 аргументом  - эвент.  Соответственно прямой вызов должен ее отдать.

Для понимания, того, что ждет  addEventListener -  вот такой бессмысленный, в данном случае код. Хотя, иногда может возникнуть ситуация, когда  нужны какие то данные, которых в элементе нет, но в момент обхода (HTMLCollection в вашем случае или NodeList если querySelectorAll) они есть.

let div = document.getElementsByTagName('div');
for (let i=0; i< div.length; i++){
  div[i].addEventListener('click', go(i));
}
function go(i) {
  return function(){
    div[i].innerHTML =  div[i].innerHTML +  div[i].dataset.num
  }
}
console.log(go) #просто посмотреть, что это

Доки это супер нужная и важная вещь,  но: есть ф12/консоль. Оттуда можно понять  

let divs = document.querySelectorAll('div.sssy');

divs.forEach(el=>{
el.addEventListener('click',
function(e){
console.log(
e.target.dataset.num,
this.dataset,
e, # какой то pageX и еще куча всего
e.target, # el = e.target = this
el,
this)
});
});

И уже тогда в гугл 

D
На сайте с 28.06.2008
Offline
980
#4

Правильно ли я понимаю?

1. addEventListener('click', go) - обработчик события вызовет функцию go только когда произойдет триггер события click?

2. Если указать круглые скобки 

addEventListener('click', go(i)) или addEventListener('click', go()) - функция go вызовется сразу как только интерпретатор дойдет до нее ?


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

addEventListener('click', function (){go(i)});

T7
На сайте с 19.09.2018
Offline
34
#5
Dram #:
addEventListener('click', function (){go(i)});

Попробуйте посмотреть, что получится, если div изменится где то ниже. Что  div[i] в вашей функции покажет. Лучше сделать примерно так, как выше написал  ArbNet 

let div = document.getElementsByTagName('div');

   for (let i=0; i< div.length; i++){
       div[i].addEventListener('click', function(){go(i)});
   }
    function go(i) {
        div[i].innerHTML =  div[i].innerHTML +  div[i].dataset.num
    }

..........
...........
div = 22
D
На сайте с 28.06.2008
Offline
980
#6

timo-71 мне уже давно не интересно как тут нужно сделать ПРАВИЛЬНО, мне хочется понять как реально работает  addEventListener, прошу, ответьте на эти вопросы? Я перечитал главу https://learn.javascript.ru/introduction-browser-events и не нашел там ответы на эти вопросы.

Правильно ли я понимаю?

1. addEventListener('click', go) - обработчик события вызовет функцию go только когда произойдет триггер события click?

2. Если указать круглые скобки 

addEventListener('click', go(i)) или addEventListener('click', go()) - функция go вызовется сразу как только интерпретатор дойдет до нее ?

ArbNet
На сайте с 27.10.2019
Offline
52
#7

Вы наверно с закрытыми глазами читаете.. или соображение напрочь отсутствует..

скрин с learn.javascript.ru/introduction-browser-event

Но 1,2 п. - поняли правильно 😀 addEventListener работает аналогично

Синтаксис добавления обработчика:

element . addEventListener ( event , handler [ , options ] ) ;

event Имя события, например  "click" .

handler Ссылка на функцию-обработчик. ===>  Функция должна быть присвоена как sayThanks , а не sayThanks()

options Дополнительный объект со свойствами:

T7
На сайте с 19.09.2018
Offline
34
#8
Dram #:

Правильно ли я понимаю?

1. addEventListener('click', go) - обработчик события вызовет функцию go только когда произойдет триггер события click?

2. Если указать круглые скобки 

addEventListener('click', go(i)) или addEventListener('click', go()) - функция go вызовется сразу как только интерпретатор дойдет до нее ?

1. Функция  addEventListener вторым параметром получит ссылку на go, которая в вашем случает является функцией

2.  Функция  addEventListener получит результат выполнения функции  go

Для понимания

function a(){
  return 22
}
console.log(typeof a, typeof a())
//вернет function number
D
На сайте с 28.06.2008
Offline
980
#9
ArbNet - спасибо, реально ведь все расписано! Извиняюсь!

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий