Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiency of adding a listener to a jQuery class set, compared to using $.each

Initial instincts tell me that adding a listener, either using bind or a straightforward event method to a jQuery set of elements, such as..

$('.className').click(funcName);

Is much more appropriate than using a $.each method to add a listener one by one to the same set, as...

$('.className').each(function(){ $(this).click(funcName); });

But when it comes to plugin development, and you are dealing with the possibility of users calling an instance of your plugin multiple times throughout the lifetime of a page, on page load and through ajax long after page load, is it wrong to apply handlers to each element itself, rather than trying to abstract the handlers to their global class set?

My main question I'm dealing with is "What is the best way to deal with multiple instances of a plugin being called when it comes to event handling? As to reduce the workload?" I know we can bind and unbind, but is there a better way?

EDIT

partial code from plugin construct

init : function(){

  this.each(function(opts){

  // adding event handlers here removes
  // the need to worry about multiple instances
  // and duplicate handles over the lifetime of the page

  });

  // adding 'global' handlers here may/may not be more
  // efficient, but adds an issue of multiple instances

  return this;

}
like image 303
anson Avatar asked May 09 '12 15:05

anson


2 Answers

If you call click once, jQuery will loop through the whole collection and bind the events individually. However, it will do it more efficiently than your alternative, because it does not build a new jQuery object for each element in the set, which will be very slow.

Here is the code from the jQuery source (it's the on method):

return this.each( function() {
    jQuery.event.add( this, types, fn, data, selector );
});

(event.js, line 936-8)

jQuery.event.add, which is the method that does the heavy lifting, does not need a jQuery object; the plain DOM object is what it needs. This loop (which effectively does the same thing as yours) is much superior in terms of efficiency, because the big bottleneck in your code is $(this) being called every time.

Note that the most efficient technique would be using event delegation with the same on method. This might look like this:

$(document.body).on('click', '.className', funcName);

This means "for every click inside document.body, check to see if it originated on an element matching the selector .className, and if so run funcName". You could replace document.body with any other element that contains all the potential .className elements.`

like image 58
lonesomeday Avatar answered Oct 23 '22 05:10

lonesomeday


Your question is about "efficiency," which I assumes means "speed on the client". Probably any reasonable approach will have minimal impact on perceived performance, so I recommend you pick the coding pattern that is easiest to maintain.

like image 32
Yusuf X Avatar answered Oct 23 '22 05:10

Yusuf X