addEventListener, for(), index. how to use closure?

Toni Michel Caubet picture Toni Michel Caubet · Dec 14, 2013 · Viewed 8.4k times · Source

I have this code:

var items = this.llistat.getElementsByTagName('a');

for( var i = 0; i < items.length; i++ ){    
  items[i].addEventListener('click', function(event) {
    alert( i );
  }, items[i]);
}

where the event is listened, but there are 3 items and the alert allways print 3 on any of the elements (it doesn't respect the index),

Dosen't items[i] shouldn't do the job as closure?

thanks!

Answer

Oriol picture Oriol · Dec 14, 2013

No, the third argument of addEventListener is the useCapture one. See MDN for more information.

But you can use:

for( var i = 0; i < items.length; i++ ){
    (function(i){
        items[i].addEventListener('click', function(event) {
            alert( i );
        }, false);
    })(i);
}

or

var handler = function(event) {
    var i = items.indexOf(this);
    alert( i );
};
for( var i = 0; i < items.length; i++ ){
    items[i].addEventListener('click', handler, false);
}

The first one creates a new event handler for each element, so it needs more memory. The second one reuses the same event listener, but uses indexOf, so it's more slow.