Reputation: 8882
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
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...
// 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
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