Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Is using $("#vacations").find("li").last() is a better practice than $("#vacations li:last")?

Background and my thoughts:

I was playing with a nice interactive try jQuery tutorial and one of the tasks says:

As you are looking through your code, you notice that someone else is selecting the last vacation with: $("#vacations li:last"). You look at this and you think, "Traversal would make this way faster!" You should act on those thoughts, refactor this code to find the last li within #vacations using traversal instead.

Why would I think so? For me usage of selectors looks a bit higher level than traversing. In my mind when I am specifying a selector it is up to jQuery how to better get the single result I need (without need in returning interim results).

What is that extra overhead of using composite selectors? Is it because current implementation of selectors logic just parses the string and uses the traversal API? Is parsing a string that slow? Is there a chance that a future implementation will use that fact that it does not need to return interim results and will be faster than traversal?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
130 views
Welcome To Ask or Share your Answers For Others

1 Answer

There's no cut and dry answer to this, but with respect to the :last selector you're using, it's a proprietary extension to the Selectors API standard. Because of this, it isn't valid to use with the native .querySelectorAll method.

What Sizzle does is basically try to use your selector with .querySelectorAll, and if it throws an Exception due to an invalid selector, it'll default to a purely JavaScript based DOM selection/filtering.

This means including selectors like :last will cause you to not get the speed boost of DOM selection with native code.

Furthermore, there are optimizations included so that when your selector is very simple, like just an ID or an element name, the native getElementById and getElementsByTagName will be used, which are extremely fast; usually even faster than querySelectorAll.

And since the .last() method just grabs the last item in the collection instead of filtering all the items, which is what Sizzle filters normally do (at least they used to), that also will give a boost.

IMO, keep away from the proprietary stuff. Now that .querySelectorAll is pretty much ubiquitous, there are real advantages to only using standards-compliant selectors. Do any further filtering post DOM selection.


In the case of $("#vacations").find("li"), don't worry about the interim results. This will use getElementById followed by getElementsByTagName, and will be extremely fast.

If you're really super concerned about speed, reduce your usage of jQuery, and use the DOM directly.


You'll currently find notes in the docs for selectors like :last, that warn you about the performance loss:

Because :last is a jQuery extension and not part of the CSS specification, queries using :last cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :last to select elements, first select the elements using a pure CSS selector, then use .filter(":last").

But I'd disagree that .filter(":last") would be a good substitute. Much better would be methods like .last() that will target the element directly instead of filtering the set. I have a feeling that they just want people to keep using their non-standards-compliant selectors. IMO, you're better of just forgetting about them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...