Best method to select an object from another unknown jQuery object
Asked Answered
A

5

8

Lets say I have a jQuery object/collection stored in a variable named obj, which should contain a DOM element with an id named target.

I don't know in advance if target will be a child in obj, i.e.:

obj = $('<div id="parent"><div id="target"></div></div>');

or if obj equals target, i.e.:

obj = $('<div id="target"></div>');

or if target is a top-level element inside obj, i.e.:

obj = $('<div id="target"/><span id="other"/>');

I need a way to select target from obj, but I don't know in advance when to use .find and when to use .filter.

What would be the fastest and/or most concise method of extracting target from obj?

What I've come up with is:

var $target = obj.find("#target").add(obj.filter("#target"));

UPDATE I'm adding solutions to a JSPERF test page to see which one is the best. Currently my solution is still the fastest. Here is the link, please run the tests so that we'll have more data:

http://jsperf.com/jquery-selecting-objects

Astonishment answered 25/5, 2014 at 11:53 Comment(4)
Question: You have target Id in your hand ,then why you have to filter or find from an object ? you could just utilize $("#target") or document.getElementById("target").(Id is unique for a page ryt ) just asked out of curiosity.Insensate
$obj.find('#target').andSelf().filter('#target'); ?Lamellicorn
@Lamellicorn It is still a bit slower than my method. See: jsperf.com/jquery-selecting-objects/12Astonishment
Yeah, I already checked that. Hence, commented. It's not so slow and is a lot clean.Lamellicorn
G
2

Ties with the fastest:

var $target = obj.find('#target').addBack('#target')
Gonzalez answered 29/5, 2014 at 2:59 Comment(4)
Yes, but this version does not find elements that are "grandchildren" of the parent, only direct children. Changing the version to use "find" is actually still a bit slower, see: jsperf.com/jquery-selecting-objects/12Astonishment
Updated with a solution that is neck and neck with yours; seems a little more readable too.Gonzalez
Clean, solves the problem and indeed neck-to-neck with my solution. Well done :)Astonishment
Nice - that was fun! Thanks for the Question.Gonzalez
A
4

What I've come up with is:

var $target = obj.find("#target").add(obj.filter("#target"));

Currently my solution is still the fastest. Here is the link, please run the tests so that we'll have more data:

http://jsperf.com/jquery-selecting-objects

Astonishment answered 28/5, 2014 at 14:36 Comment(0)
R
2

You can wrap the collection with another element and use the find method:

obj.wrap('<div/>').parent().find('selector');

If you're worried about performance, you should not use jQuery in the first place. Vanilla JavaScript is always faster than jQuery.

An alternative is using the querySelector or querySelectorAll method:

function find(html, selector) {
   var temp = document.createElement('div');
   temp.innerHTML = html;
   return [].slice.call(temp.querySelectorAll(selector));    
};
Relative answered 25/5, 2014 at 12:8 Comment(3)
Thanks! Is this indeed faster than making 2 queries?Astonishment
Thanks, I just did and the result I got show that 2 queries are indeed faster: jsperf.com/jquery-selecting-objectsAstonishment
@Yosi That's interesting, wrap is much slower.Relative
G
2

Ties with the fastest:

var $target = obj.find('#target').addBack('#target')
Gonzalez answered 29/5, 2014 at 2:59 Comment(4)
Yes, but this version does not find elements that are "grandchildren" of the parent, only direct children. Changing the version to use "find" is actually still a bit slower, see: jsperf.com/jquery-selecting-objects/12Astonishment
Updated with a solution that is neck and neck with yours; seems a little more readable too.Gonzalez
Clean, solves the problem and indeed neck-to-neck with my solution. Well done :)Astonishment
Nice - that was fun! Thanks for the Question.Gonzalez
K
0

You can start off with a fresh <div/> and append obj to it, then do the search:

$( '<div/>' ).append( obj ).find( '#target' );

Of the three, this is the second fastest.

Kellyekellyn answered 29/5, 2014 at 1:29 Comment(0)
B
0

I would go for the wrap > find solution because it is the most readable (and I doubt you need to optimise performance any further). But performance wise, you should be running only the methods you need, until you need:

var getTarget = function(b){
  for(i=0; i<b.length; i++){
    if(b[i].id === 'target'){
      return $(b[i]);
    } else {
      var $target = b.find('#target');
      if($target.length > 0){ return $target }
    }
  }
}

var $target = getTartget( obj );

http://jsperf.com/jquery-selecting-objects/6

Butt answered 29/5, 2014 at 5:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.