2

I already saw this question on SO: JavaScript: remove event listener

I understand what it does. But I don't know why addEventListener will sometimes accumulate overtime whereas other times it doesn't.

My understanding from toying with my code is that accumulation only happens when there is addEventListeners nested in another addEventListener? Could someone explain why this happens?

http://jsfiddle.net/dTx72/1/

In my demo above, I just have a div with a button inside. I have added an addEventListener to the div and to the button. When the button is clicked, an alert pops up.

<div id='clickBox'>
  <button id='button'>Click Me</button>
</div> 

Javascript

 document.getElementById('clickBox').addEventListener('click', function () {
    alert('hello');
    document.getElementById('button').addEventListener('click', function () {
      alert('accumulates per click');
    });
 });

The result is

  • First click: alert('hello'), alert('accumulates per click'),
  • Second click: alert('hello'), alert('accumulates per click'),alert('accumulates per click')

and so on. It's odd to me that alert('hello') wouldn't also accumulate.

Community
  • 1
  • 1
  • could you explain the -1? It doesn't help if you downvote without a reason – user3850688 Jul 21 '14 at 23:23
  • Your question is hard to answer if there is no code to review. So, we don't know how something happens we can't see. – Jorg Jul 21 '14 at 23:26
  • Oh okay, my apologies. I thought this was a common problem with an explanation behind it. Hopefully when I post a JSfiddle it wouldn't just be a dumb error that I made. – user3850688 Jul 21 '14 at 23:30
  • Because you're binding another event-handler on each click of the clickbox and also executing the previously bound listeners' functions. – David Thomas Jul 21 '14 at 23:50
  • Ah, okay I get it. I'm adding a listener on another listener so it accumulates overtime, so that's where I would use removeEventListener. Thanks – user3850688 Jul 22 '14 at 00:02
  • Not necessarily, just don't use `addEventListener` inside an `addEventListener`. Why would you even want to do it that way in the first place? – David Thomas Jul 22 '14 at 00:04
  • huh...good point.. I could just use event.target to get the child nodes, unless I wanted to use a 'hover' as a listener for a child instead of a 'click'. Unless there's a better way? – user3850688 Jul 22 '14 at 00:10
  • This isn't really worthy of an answer, but it's a handy tip if you're using jQuery: utilize the heck out of the `.remove()` and `.empty()` functions in jQuery. Doing so will remove all events attached to that element and nested elements in the DOM, thus making event-bloat a much lower risk. – Tombert Jul 22 '14 at 01:25
  • Thanks, any extra information is appreciated – user3850688 Jul 22 '14 at 03:13

2 Answers2

3

addEventListener is always accumulative. As its name says, it adds an event listener, but doesn't remove previous ones.

However, if you add the same function as an event listener for same event in same phase, that function will only run once.

Examples:

el1.addEventListener('click', f);
el1.addEventListener('click', g);
el1.click(); // f and g run once

el2.addEventListener('click', f);
el2.addEventListener('click', f);
el2.click(); // f runs once

el3.addEventListener('click', f, true);
el3.addEventListener('click', f, false);
el3.click(); // f runs twice (one during capture and one during bubbling)

el4.addEventListener('click', function(){ alert('a'); }, true);
el4.addEventListener('click', function(){ alert('a'); }, false);
el4.click(); // The function will run twice, because even if they do the same,
             // they are different functions
Oriol
  • 274,082
  • 63
  • 437
  • 513
1

When you use addEventListener, you are basically saying "When event X happens, do Y in addition to whatever else you are supposed to do. So the run of your program is:

When they click, do the following:

TASK A:
say "hello"
add a new event listener to say "accumulates" every time they click.

So they click, and NOW their list of tasks is

TASK A:
say "hello"
add a new event listener to say "accumulates" every time they click.
TASK B:
say "accumulates"

So they click, and their new list of tasks is

TASK A:
say "hello"
add a new event listener to say "accumulates" every time they click.
TASK B:
say "accumulates"
TASK C:
say "accumulates"

Every time they click, you are adding a NEW task. So whatever task you add when they click, will naturally accumulate, as you are adding the same item over and over on the "to do" list.

dave
  • 62,300
  • 5
  • 72
  • 93