views:

352

answers:

6

I have an A tag which triggers the animation of it's great-great-great-grandparent. All of the following will work, but which is most efficient, and why?

$(this).parent().parent().parent().parent().parent().animate(...);

$(this).parents(".foo").animate(...);

$(this).closest(".foo").animate(...);

I suspect that the first might be, as it's the most explicit, but for maintenance reasons (the nesting may change) I prefer the second. They all appear to run smoothly in practice.

+5  A: 

It is a very good thing that you did performance measurements. That's exactly what should be done in such scenarios. If all appear to run smoothly in practice and you are satisfied with the performance pick the most readable one (second and third look ok).

Darin Dimitrov
+2  A: 

I think I saw a presentation of John Resig saying that closest() is more optimized, and it makes some sense. Closest() is a newer addition to jQuery and comes to solve exactly this ugly parent().parent() chain. On the other hand parents() returns an array of parents that match your foo class and is more greedy in terms of searching compared with closest() that finds the first element and stops searching.

I would bet that closest() is the most efficient if you are looking for the closest match.

Elzo Valugi
+1  A: 

I can't comment on the realtive speed, however the first one ties you to an specific heirarchy of elements, which I would shy away from.

Personally, I try to use class selectors sparingly anyway. I realise there is often no other way, but if I can factor in an ID selector then I know the performance is likely to improve anyway.

James Wiseman
+11  A: 

Here’s an analyzation:

  • parent() walks just one level up in the DOM tree.
  • parents(".foo") walks up to the root and selects only those elements that match the given selector .foo.
  • closest(".foo") walks up to the root but stops once an element matches the selector .foo.

So I would choose the last one, closest(".foo"). The reason:

  • It’s better than chaining parent, because if your document changes because you removed or added one hierarchy, you don’t need to change the jQuery code.
  • It’s better than parents(".foo"), because it stops as soon as a match has been found.
Gumbo
What’s the reason for the down vote? Are there any objections to my answer?
Gumbo
+1  A: 

You also can use parents('.foo:first'). I guess is pretty much the same as closest().

Ionut Staicu
+1  A: 

A quick test in Firefox 3.6.3 reveals that parents('.foo').eq(0) is actually significantly faster than closest('.foo'). It's debatable whether it is as maintainable, but it might prove to be more 'efficient' in specific scenarios.

Wynand
If you just aim for speed, you shouldn’t use the jQuery facade at all but just simple DOM traversing: `$(this.parentNode.parentNode.parentNode.parentNode.parentNode).animate(…)`
Gumbo