Best way to get child nodes
children, dom, element, javascript
Solution
Sounds like you're overthinking it. You've observed the difference between `childNodes` and `children`, which is that `childNodes` contains all nodes, including text nodes consisting entirely of whitespace, while `children` is a collection of just the child nodes that are elements. That's really all there is to it.
There is nothing unpredictable about either collection, although there are a couple of issues to be aware of:
- IE <= 8 do not include white space-only text nodes in `childNodes` while other browsers do
- IE <= 8 includes comment nodes within `children` while other browsers only have elements
`children`, `firstElementChild` and friends are just conveniences, presenting a filtered view of the DOM restricted to just elements.
Problem
I was wondering, JavaScript offers a variety of methods to get the first child element from any element, but which is the best? By best, I mean: most cross-browser compatible, fastest, most comprehensive and predictable when it comes to behaviour. A list of methods/properties I use as aliases: ``` var elem = document.getElementById('container'); var child = elem.children[0]; var child = elem.firstElementChild; // == children[0] ``` This works for both cases: ``` var child = elem.childNodes[0]; // or childNodes[1], see below ``` That’s in case of forms, or `<div>` iteration. If I might encounter text elements: ``` var child = elem.childNodes; // treat as NodeList var child = elem.firstChild; ``` As far as I can work out, `firstChild` uses the NodeList from `childNodes`, and `firstElementChild` uses `children`. I’m basing this assumption on the MDN reference: `childNode` is a reference to the first child element of the element node, or `null` if there isn’t one. I’m guessing that, in terms of speed, the difference, if any, will be next to nothing, since `firstElementChild` is effectively a reference to `children[0]`, and the `children` object is already in memory anyway. What does throw me, is the `childNodes` object. I’ve used it to take a look at a form, in a table element. While `children` lists all form elements, `childNodes` also seems to include whitespace from the HTML code: ``` console.log(elem.childNodes[0]); console.log(elem.firstChild); ``` Both log `<TextNode textContent="\n ">` ``` console.log(elem.childNodes[1]); console.log(elem.children[0]); console.log(elem.firstElementChild); ``` All log `<input type="text"`…`>`. How come? I’d understand that one object would allow me to work with the “raw” HTML code, while the other sticks to the DOM, but the `childNodes` element seems to work on both levels. To get back to my initial question, my guess would be: if I want the most comprehensive object, `childNodes` is the way to go, but because of its comprehensiveness, it might not be the most predictable in terms of it returning the element I want/expect at any given moment. Cross-browser support might also prove to be a challenge in that case, though I could be wrong. Could anyone clarify the distinction between the objects at hand? If there is a speed difference, however negligible, I’d like to know, too. If I’m seeing this all wrong, feel free to educate me. PS: Please, please, I like JavaScript, so yes, I want to deal with this sort of thing. Answers like “jQuery deals with this for you” are not what I’m looking for, hence no jquery tag.