KodeKreachor
KodeKreachor

Reputation: 8882

Does chaining jQuery selectors have any negative effects?

Are there any negative implications to chaining jQuery API calls on a selector? Negative implications dealing with performance, design, susceptibility to memory leaks are what I'm particularly interested in.

So, would chaining a statement such as this:

$('.myElement').css('color','green')
               .attr('title','My Element')
               .click(function(){ console.log('clicked') });

Leave the application open to any of the aforementioned negative implications?

I personally don't have any problems with chaining jQuery expressions at all, but I've seen a lot of people bash chaining and I want to know if there is any concrete benefits of avoiding it, or if it's just a matter of readability and personal style.

Upvotes: 4

Views: 664

Answers (2)

user1106925
user1106925

Reputation:

Chaining is just invoking a method on a returned object. There's nothing inherently good or bad about that. Some like it, some don't.


With respect to memory leaks, jQuery does keep a cached set of jQuery objects when you've done DOM traversal. This doesn't really have much to do with chaining, since a referenced jQuery object will do the same thing, but I suppose it could cause a leak if you keep a permanent reference to the object.


For example, if you do this...

var jq_obj = $('.my_class').parents('.another_class');

...the jQuery object now has a reference to ancestors of the ".my_class" elements that have the ".another_class" class.

The thing is that you can then do this...

jq_obj.end();

...and you now have a reference to the original ".my_class" elements selected. This means that the original references were maintained.


So if after calling .parents(), if you stopped there (didn't call .end()), and if you kept a global reference to that jq_obj object, you'd now have an implicit reference to all the ".my_class" elements in addition to the ".another_class" elements.

As such, if any of the original ".my_class" elements are removed from the DOM, they can't be GC'd because of that reference.


Here's an example...

http://jsfiddle.net/aUEFc/

   // select "my_class" then traverse to a parent
var jq_obj = $('.my_class').parents('.another_class');

   // remove "my_class" elements from the DOM
$('.my_class').remove();

   // see if we still have a reference to "my_class" elements
var len = jq_obj.prevObject.filter('.my_class').length;

The len variable will be the original number of ".my_class" elements that were selected even though the ".my_class" elements were removed.

This is the case even though our jq_obj object is referencing the ".another_class" elements. The reason is that the .prevObject property references the jQuery object that did the original DOM selection, so the nodes are never released as long as jq_obj survives.

Upvotes: 2

John Shepard
John Shepard

Reputation: 947

Chaining is actually better than doing this:

$('.myElement').css('color','green')
$('.myElement').attr('title','My Element')
$('.myElement').click(function(){ console.log('clicked') });

Since doing so would make jquery 'jump into the pool' looking for my element 3 times, while if you chain your orders it will just look in the pool once (notice the pool is the DOM :)

Upvotes: 4

Related Questions