TeRrIrAoLr
TeRrIrAoLr

Reputation: 221

When are duplicate event listeners discarded, and when are they not?

I'm having trouble understanding why the "duplicate" event listeners created in the following examples behave so differently. I've perused several discussions about the topic, but I'm just starting to learn JavaScript, and I can't quite figure out what's happening in Version 2 that isn't happening in Version 1. Would anyone be willing to enlighten me?

Here's a JSFiddle demo. The JavaScript looks like this:

// VERSION 1

   var clickEvents = 0;

   button.addEventListener('click', buttonFunction);

   function buttonFunction() {
     clickEvents++;
     display.innerHTML = clickEvents;  // <-- increases incrementally 
     button.addEventListener('click', buttonFunction);
     }

// VERSION 2

   var clickEvents = 0;

   mainFunction();

   function mainFunction() {

     button.addEventListener('click', buttonFunction);

     function buttonFunction() {
       clickEvents++;
       display.innerHTML = clickEvents;  // <-- increases exponentially
       mainFunction();
       }
     }

Upvotes: 1

Views: 2017

Answers (1)

Tibrogargan
Tibrogargan

Reputation: 4603

The behavior is due to scoping. In version 1, you're adding the globally scoped function . When you try to add it again it silently fails because the function is already registered. From MDN:

Multiple identical event listeners

If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and they do not need to be removed manually with the removeEventListener method.

In version 2, because the buttonFunction declared inside mainFunction is locally scoped it is not the same as the global function and every time you call it mainFunction you get a different version since the scope is changing. Because the JS Engine considers the functions to be different when you call addEventListener each one is added independantly. Every time you click the button you're doubling the number of listeners attached to the button.

The snippet demonstrates that the JS Engine considers each invocation of bar() to have a different local foo

function foo() {
    console.log("global");
}

function bar() {
    function foo() {
	    console.log("local");
    }
    return foo;
}

var oneG = foo;
var twoG = foo;
var oneL = bar();
var twoL = bar();

console.log(`Global: ${oneG === twoG}`);
console.log(`Local: ${oneL === twoL}`);

Upvotes: 1

Related Questions