views:

88

answers:

5

Is this faster:

$(document.links).filter('a.someClass')

than just plain old this:

$('a.someClass')

?

I don't see anywhere in jQuery's code the utilization of document.links
which gives you the collection of links on the document right away,
than, it would seem, it would be faster to just filter in the collection
instead of all the DOM nodes, which is alot more nodes to go over.

+1  A: 

Don't second-guess jQuery. Lots of people have spent lots of time making it fast. If it were the case that document.links were a good way to find <a> tags, then Sizzle would do it automatically for you.

That said (well, typed), it's definitely better to do this:

$('a.someClass')

than

$('.someClass')

When you can qualify your selectors with a tag name, you're better off. The engine will use getElementsByTagName() to cut down on the number of nodes to scan.

Pointy
Pointy
April's fools I suppose :p
vsync
It's for april fools, they had a cornify button last year, unicorn avatars this year.I guess the SO team really like unicorns :)
Neil Aitken
ah, i just received 555 points, thought it was some kind of 'special number' and therefore i received the special avatar :)
Michel
@Michel I guess that would be a truly magic number. (I assume unicorns are magical, if not my entire world view will be destroyed) :)
Neil Aitken
I hate it when i step into the April's fools jokes :) Especially when i've been learning my little daughters a few basic ones these morning, and now already i forgot the date!
Michel
A: 

I'm not familiar with how the sizzle selector library works but I would suspect when you do $('a.someclass') that jQuery will retrieve all the anchors using something like document.getElementByTagName('A') rather than traversing the whole DOM.

As Pointy says, sizzle is very fast and highly optimised, best way to find out which is better would be to run your own benchmarks

Neil Aitken
so what's faster, document.getElementByTagName('A') or document.links? :p hmmm
vsync
@vsync: When don't you do a micro benchmark and tell us? ;)
Jørn Schou-Rode
No idea, I haven't tested both. Also consider that jQuery has to handle all elements, so it may not have made sense to use a special case just for anchors when a more general approach would do.
Neil Aitken
+6  A: 

I just ran a test, running the selector 1000 times on Chrome.

$(document.links).filter('a.someClass') took 672 ms to run 1000 times.

$('a.someClass') took 191 ms to run 1000 times.

If you do

$('a').filter('.someClass') however, that takes 652 ms to run; so filter seems to be where the time is lost.

var x = $('.remove', document.links); coincidentally, took 13 seconds; so best not to use that variation :P

Matt
There's always someone who comes along to run some tests and end our petty conjecture, damn you :)
Neil Aitken
Nice man, nice! now I can get on with my life! thank you :)
vsync
I'm curious of why the document.links test took 13 seconds! it would seem far too long. you ran the selector 1000 times? on 1000 elements you had created dynamical before? you only need to run the selector once and let it fetch your collection.
vsync
@vsync: I used the BBC home page as a testing ground, because of the size of the DOM. I then ran the script you can find at http://files.mattlunn.me.uk/permanent/so_2560078.txt using Chrome's Javascript console. I know I only need to run the selector once, but the time taken to execute would be so small, all tests would return 0ms.
Matt
+1 for this one
Michel
i ran a test of my own here (use firebug to watch): http://jsbin.com/ixiva3
vsync
@vsync: Our results are pretty similar; it's significantly slower for me because whilst you only have 1,000 elements in your DOM, BBC's homepage has significantly more. BBC also has many levels of elements in various ancestor/ descendent relationships.
Matt
@Matt: BBC homepages says it has only 235 links (document.links.length)
vsync
A: 

I just ran a test here : http://jsbin.com/ixiva3

1000 links were created dynamically. this test require firebug (using console.time)

Results shows that $("a.somelink") is the fastest.

vsync
+1  A: 

Theoretically, iterating document.links will be a bit faster than jQuery's Sizzle selector library. However:

  • not the way you're doing it with filter, which gives jQuery just as much work to do than it would have to do using Sizzle to pick the elements in the first place;

  • document.links won't necessarily give you exactly the same as $('a'), as a-without-href doesn't appear in the links collection.

  • the direct $('a.someClass') method will be much faster than even manually iterating document.links in modern browsers, because that method will just transfer control to the browser's own implementation of document.querySelectorAll('a.someClass'), which will be much faster than anything your or Sizzle could do sniffing at DOM Nodes yourself.

(There is one slightly faster method than querySelectorAll, which jQuery doesn't use yet: document.getElementsByClassName('someClass'). Again, it's only in modern browsers though, and IE8 doesn't have it where it does have querySelectorAll. In practice it's probably not worth bothering about too much as querySelectorAll is already very fast.)

bobince
Excellent answer, thanks!
vsync