11

I am working with a dashboard of divs and each div it has a tree of which the buttons are. Every time I have to know which the id of that div is so I am using parent() alot.

Mostly I am doing $(this).parent().parent().parent() to find the ID of div so I can set variables to it. The app is based on the id's of each div.

Is it consider slow to use parent() up to 3 times but pretty much on every function?

Is there any other alternative?

I am looking for something like benchmarks-style which shows what's faster.

Here is an example of the tree:

<div id="6179827893" class="dashdiv">
   <div class="buttons">
     <li><a href="#" class="btn1">Button 1</a></li>
     <li><a href="#" class="btn2">Button 2</a></li>
     <li><a href="#" class="btn3">Button 3</a></li>
     <li><a href="#" class="btn4">Button 4</a></li>
     <li><a href="#" class="btn5">Button 5</a></li>
     <li><a href="#" class="btn6">Button 6</a></li>
   </div>
   <div class="dashcontent">

    ....

   </div>
</div>
jQuerybeast
  • 13,038
  • 35
  • 114
  • 189

4 Answers4

19

You've got a few options to achieve the same effect.

Benchmark: http://jsperf.com/parents-method. According to this benchmark, my method is roughly 100x faster than your method.

Method (see below) : Operations per second (higher is better)
parentNode3x       : 4447k
$(parentNode3x)    :  204K
$().closest        :   35k
$().parents        :    9k
$().parent()3x     :   44k

// Likely the fastest way, because no overhead of jQuery is involved.
var id = this.parentNode.parentNode.parentNode.id;

// Alternative methods to select the 3rd parent:
$(this.parentNode.parentNode.parentNode) // Native DOM, wrapped in jQuery

// Slowpokes
$(this).closest('.dashdiv')              // Hmm.
$(this).parents('.dashdiv:first')        // Hmm...
Rob W
  • 315,396
  • 71
  • 752
  • 644
  • Is your second option faster than what I have? I suppose parentNode means parent() – jQuerybeast Jan 09 '12 at 13:52
  • Thank you and for the benchmark. Pretty much what I was looking for – jQuerybeast Jan 09 '12 at 14:00
  • As you can see, native DOM/JavaScript is always as fast/faster than jQuery. Unless you encounter crossbrowser issues, it's more efficient to write code in pure JavaScript, especially if you're calling the code several times, such as in an interval, loop or frequently occurring event. – Rob W Jan 09 '12 at 14:03
  • 3
    @RobW Don't say "better", say "more efficient". "Better" is relative. If I were a second developer looking at this user's code and I saw it littered with `node.parentNode.parentNode.parentNode.id` without a good comment explaining why, I'd swear under my breath at him and start rewriting immediately. – Blazemonger Jan 09 '12 at 14:07
  • just changed a bunch of code based on this. Thanks Rob. – cpk May 25 '14 at 23:55
9

You might be better off using .closest(), like this: $(this).closest('.dashdiv')

It's not any faster from an engine's point of view, since you're still looping up through the DOM layers, but it's more clear to a newcomer as well as shorter code.

COMMENTARY

If it's pure speed you're after, you might as well skip jQuery entirely and use node.parentNode instead. But this is getting into niggly issues of counting cycles, and I think it's an academic one.

If you're writing high-performance code for major production, like a commercial search engine or webmail provider, then counting cycles is important because any small optimization gets multiplied thousands of times. With all due respect, I doubt you're writing that kind of code.

If you're writing something that's going to be hit by a few people at a time, at most, then small optimizations are an intellectual exercise that won't affect results in any noticable way. You'd have to improve your code's efficiency by hundreds of milliseconds before any user would even begin to notice, and this code isn't going to do that.

Instead, it's far more important to think about the next developer who will be looking at your code. For that developer, it's important to have clear, well-written code that immediately communicates what it's doing. Eye-blurring chains of methods like parent().parent().parent() can obscure and confuse other developers, to say nothing of node.parentNode.parentNode.parentNode

-- which is why .closest() was created in the first place. It's clear, concise, and not noticably less efficient than the chains it replaces. 999 times out of a thousand, it's the way you ought to go.

Blazemonger
  • 82,329
  • 24
  • 132
  • 176
  • closest isn't considered faster. jQuery has to search for the closer where parents doesnt – jQuerybeast Jan 09 '12 at 13:50
  • Yes, that was my thought. But I think there's a small sacrifice to be made here in exchange for clearer, more concise code. If it's pure speed you're after, you might as well skip jQuery entirely and use [`node.parentNode`](https://developer.mozilla.org/En/DOM/Node.parentNode) instead. – Blazemonger Jan 09 '12 at 13:52
  • Thank you. Well answered. Selected Rob's answer as its what I will be using and for the benchmark – jQuerybeast Jan 09 '12 at 14:07
2

First, don't optimise prematurely. If it's not causing a problem (and test thoroughly by all means, across a range of platforms) then don't worry about it.

There is a possible optimisation: use native DOM properties:

var id = this.parentNode.parentNode.parentNode.id;

Note that the nicest jQuery way to do this (which will be slower, but that may not be a problem) is with closest:

$(this).closest('div.dashdiv').prop('id');
lonesomeday
  • 215,182
  • 48
  • 300
  • 305
  • I am aware of closest but its probably the slowest of all and as the app gets larger and larger that will be a pain. I suppose as Rob W stated, parentNode will be the faster right? – jQuerybeast Jan 09 '12 at 13:54
  • 1
    @jQuerybeast Yes: [it's what jQuery uses internally](https://github.com/jquery/jquery/blob/master/src/traversing.js#L179). – lonesomeday Jan 09 '12 at 13:55
  • Ha! Nice one on the link. Considering your 'don't optimise prematurely' Im not sure whether I should swap parent() with parentNode or leave it as it is – jQuerybeast Jan 09 '12 at 13:57
  • Thank you for your answer. I will be selecting Rob's answer since its pretty much the same but he answered first – jQuerybeast Jan 09 '12 at 14:00
1

If the handlers are currently on the <a> elements, place them on the .dashdiv elements instead.

Then you can do this.id if the e.target was an <a> element.

$('.dashdiv').click(function(e) {
    if( e.target.nodeName.toLowerCase() === 'a' ) {
        alert( this.id );
    }
});