Skip to content

Evaluate (when available) use of DOM Element#closest method #1868

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
markelog opened this issue Nov 13, 2014 · 19 comments
Open

Evaluate (when available) use of DOM Element#closest method #1868

markelog opened this issue Nov 13, 2014 · 19 comments
Assignees
Milestone

Comments

@markelog
Copy link
Member

markelog commented Nov 13, 2014

Specification - https://dom.spec.whatwg.org/#dom-element-closest

Its signature is pretty close to ours, it might beneficial to use it

@dmethvin
Copy link
Member

We could only use it for cases where the selector has no jQuery selector extensions. I suppose we could try to validate it by calling querySelectorAll() with the selector string and seeing if it throws, then use the DOM method if it didn't. Or maybe we just call DOM .closest() directly and wrap that in a try/catch.

Given how crappy the performance usually is on newer DOM/ES5+ methods it would be worth benchmarking to see if it's worth the effort.

@mgol
Copy link
Member

mgol commented Nov 13, 2014

We could only use it for cases where the selector has no jQuery selector extensions.

Unless jquery/sizzle#293 is accepted. :)

@markelog
Copy link
Member Author

Yep, i suspect there should be some pitfalls like that, i would like to see something like this as resolution of this issue.

@paulirish
Copy link
Member

elem.closest() is in Chrome 40, which has been in Canary & Dev for a while. it'll be coming to beta in a wink.

@markelog
Copy link
Member Author

Yep, that's why I created this issue now

@dmethvin
Copy link
Member

We're WAAAY ahead of you, nyah-nyah! 😜

@paulirish
Copy link
Member

:p

On Tue Nov 18 2014 at 8:58:43 PM Dave Methvin notifications@github.com
wrote:

We're WAAAY ahead of you, nyah-nyah! [image:
😜]


Reply to this email directly or view it on GitHub
#1868 (comment).

@dmethvin
Copy link
Member

dmethvin commented Dec 5, 2014

True, but it's currently not slow. Chrome is doing 30k ops/sec with today's code and Firefox is 50k. Considering all that we do there I'm surprised it's only about 5x faster! Plus we can't avoid having the current code path, we'll have to add another path being sure to call the old path for cases where querySelectorAll doesn't work, such as broken qSA or jQuery selector extensions.

@markelog
Copy link
Member Author

markelog commented Dec 5, 2014

Right, that is way i said we need comprehensive research (including implementation details) and not just one perf link.

@paulirish
Copy link
Member

Haha, guys!! I'm merely just cross linking relevant stuff. Its also
worthwhile to show this is not a classList situation where native is
slower.

No rush from me. I'm so chill.

@timmywil
Copy link
Member

Now that we've removed the pos exception from closest, I think it's time to give this another look.

@timmywil timmywil added this to the 3.1.0 milestone Jan 15, 2016
@dmethvin
Copy link
Member

Oh yeah, awesome! Good call on removing positional selectors @gibson042!

@oriadam
Copy link

oriadam commented Apr 12, 2016

Any news here guys? The performance difference is noticeable.
In my personal experience, replacing $(this).closest('tr') to $(this.closest('tr')) when traversing through a table saved whole seconds. The test to determine if a selector is qsa or sizzle compatible surely exists somewhere in the code, but I can't find it.
As a quick and safe solution we can check for ':' to improve speed of most use cases.

@dmethvin
Copy link
Member

Do you have your test case? (Not a jsperf, but real code.) It's hard for me to imagine situations where this would save seconds, but the code could clarify it.

@oriadam
Copy link

oriadam commented Apr 12, 2016

The different isn't too big in simple examples - something like 30-50ms for 2000 calls.
But when the element does not exist, which is not uncommon in real-life, the difference is seconds.

The actual code is very complex and has no public access anyway.
I tried my best to mimic the structure of the real code, omitting anything irrelevant:
https://jsfiddle.net/oriadam/vcs73d1q/3/

Uncomment line 5 to see the timing when using jQuery's closest.

@timmywil timmywil self-assigned this Sep 26, 2016
@timmywil timmywil modified the milestones: 3.3.0, 3.2.0 Feb 27, 2017
@timmywil timmywil modified the milestones: 3.3.0, Future Dec 18, 2017
@NN---
Copy link

NN--- commented Feb 4, 2018

@oriadam In websites with deep tree native closest much times faster than jQuery.
You can see it in gmail for example.

Just try in dev console:

// 50
e=document.querySelector('#\\3a 3b > div > div > div'); start=performance.now(); for(i=0;i<100000;i++) e.closest('body'); console.log(performance.now()-start);
// 2800
e=jQuery(document.querySelector('#\\3a 3b > div > div > div')); start=performance.now(); for(i=0;i<100000;i++) e.closest('body'); console.log(performance.now()-start);

@dmethvin
Copy link
Member

dmethvin commented Feb 4, 2018

If you need to find the closest ancestor of 100,000 nodes in a short period of time I would definitely recommend using the native method directly. It would be a good optimization for a case like that, but I wouldn't do it until the profiler shows that .closest() is an actual bottleneck in the code. I suspect that is rarely the case.

@NN---
Copy link

NN--- commented Feb 4, 2018

My real problem is IE which works significantly slower than Chrome and doesn't support any native optimization :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

7 participants