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

BlueYoshi
  • 1,534
  • 12
  • 18
  • 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. – Thi49 May 29 '14 at 04:33
  • `$obj.find('#target').andSelf().filter('#target');` ? – Jashwant May 29 '14 at 12:13
  • @Jashwant It is still a bit slower than my method. See: http://jsperf.com/jquery-selecting-objects/12 – BlueYoshi Jun 01 '14 at 11:19
  • Yeah, I already checked that. Hence, commented. It's not so slow and is a lot clean. – Jashwant Jun 01 '14 at 17:05

5 Answers5

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

BlueYoshi
  • 1,534
  • 12
  • 18
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));    
};
Ram
  • 143,282
  • 16
  • 168
  • 197
2

Ties with the fastest:

var $target = obj.find('#target').addBack('#target')
jurassix
  • 1,509
  • 10
  • 10
  • 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: http://jsperf.com/jquery-selecting-objects/12 – BlueYoshi Jun 01 '14 at 11:17
  • Updated with a solution that is neck and neck with yours; seems a little more readable too. – jurassix Jun 03 '14 at 01:53
  • Clean, solves the problem and indeed neck-to-neck with my solution. Well done :) – BlueYoshi Jun 03 '14 at 10:36
  • Nice - that was fun! Thanks for the Question. – jurassix Jun 03 '14 at 12:30
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.

PeterKA
  • 24,158
  • 5
  • 26
  • 48
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

Hugo Silva
  • 6,748
  • 3
  • 25
  • 42