hasChildNodes vs firstChild
Asked Answered
P

5

5
while (div.hasChildNodes()) {
    fragment.appendChild(div.firstChild)
}

while (div.firstChild) {
    fragment.appendChild(div.firstChild)
}

Comparing the two pieces of pseudo code above, they both append each child of div to fragment until there are no more children.

  1. When would you favour hasChildNodes or firstChild they seem identical.
  2. If the APIs are so similar then why do they both exist. Why does hasChildNodes() exist when I can just coerce firstChild from null to false
Pentheus answered 13/4, 2012 at 1:13 Comment(6)
Stab in the dark, but wouldn't div.firstChild be faster because it's a static value as opposed to div.hasChildNodes(), which is a lookup function to be called?Preceptive
@ElliotBonneville it completely depends on the implementation. It's possible that coercing div.firstChild to boolean is faster than the function call overhead, but without measuring, there is no way to definitively know.Tegular
@Elliot: Just because it isn't a function doesn't eliminate the possibility that is causes complex code to run in response to a read/write. Consider the innerHTML property of DOM elements. That causes some major activity, no?Juridical
I'd say while(var fc=div.firstChild) fragment.appendChild(fc) would another tick faster.Kimberliekimberlin
Hah! Wouldn't your pseudocode loop forever?Juridical
@Juridical No, every time you append the node to something else it gets removed as a childnode from the divPentheus
J
4

a) micro-optimization!

b) Although it seems to be common practice, I'm not fond of relying on null/non-null values being used as a substitute for false/true. It's a space saver that's unnecessary with server compression enabled (and can sometimes call subtle bugs). Opt for clarity every time, unless it's demonstrated to be causing bottlenecks.

I'd go for the first option, because it explains your intent perfectly.

Juridical answered 13/4, 2012 at 1:21 Comment(1)
@Raynos, there are many APIs that afford the user different ways of asserting the same information, especially if the language has a bit of history.Juridical
P
4

There's no functional difference between your two implementations. Both generate the same results in all circumstances.

If you wanted to pursue whether there was a performance difference between the two, you would have to run performance tests on the desired target browsers to see if there was a meaningful difference.

Here's a performance test of the two. It appears to be browser-specific for which one is faster. hasChildNodes() is significantly faster in Chrome, but firstChild is a little bit faster in IE9 and Firefox.

enter image description here

Pierce answered 13/4, 2012 at 1:24 Comment(0)
R
0

I would suggest hasChildNodes() over firstChild just due to the return; hasChildNodes() returns false if it's blank, while firstChild returns null; which allows you to parse the data more efficiently when it comes to checking if they exist. Really, it depends on how you plan on manipulating the DOM to achieve your results.

Reinhold answered 13/4, 2012 at 1:22 Comment(0)
V
0

Your two examples will usually* behave identically, aside from some (probably) negligible differences in speed.

The only reason to favor one over the other would be clarity, specifically how well each construct represents the ideas the rest of your code is implementing, modulated by whether one of them is easier for you to visually parse when you're reading the code. I suggest favoring clarity over performance or unnecessarily pedantic correctness whenever possible.

* Note: I'm assuming you're running this code on a webpage in a vaguely modern browser. If your code needs to run in other contexts, there might be a significant speed difference or even functional (side-effect) differences between .hasChildNodes() and .firstChild: One requires a function call to be set up and executed, the other requires that a script-ready DOM compliant representation of the first child be constructed if it isn't already available.

Vigor answered 13/4, 2012 at 1:50 Comment(0)
F
0

Assuming DOM calls are slow, you could optimize further (at the expense of readability) by using a single call to firstChild:

var child;
while ( (child = div.firstChild) ) {
    fragment.appendChild(child);
}

... although (bizarrely, to me) this apparently doesn't help at all and makes things worse, according to this jsPerf: http://jsperf.com/haschildnodes-vs-firstchild/2

As to why both methods exist, remember that DOM is not exclusive to JavaScript. In a Java DOM implementation, for example, you would have to explicitly compare firstChild (or more likely firstChild()) to null.

Farmergeneral answered 13/4, 2012 at 8:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.