¿Cuál es la diferencia entre child y childNodes en JavaScript?

305

Me he encontrado con JavaScript y me encontré childNodesy childrenpropiedades. Me pregunto cuál es la diferencia entre ellos. ¿También se prefiere uno al otro?

Juan
fuente

Respuestas:

330

Comprende que .childrenes una propiedad de un Elemento . 1 Solo los elementos tienen .children, y estos elementos secundarios son todos de tipo Elemento. 2

Sin embargo, .childNodeses propiedad de Node . .childNodespuede contener cualquier nodo 3

Un ejemplo concreto sería:

let el = document.createElement("div");
el.textContent = "foo";

el.childNodes.length === 1; // Contains a Text node child.
el.children.length === 0;   // No Element children.

La mayoría de las veces, desea usarlo .childrenporque generalmente no desea recorrer los nodos de Texto o Comentario en su manipulación DOM.

Si desea manipular nodos de texto, probablemente lo desee .textContent. 4 4


1. Técnicamente, es un atributo de ParentNode , un mixin incluido por Element.
2. Todos son elementos porque .childrenes una colección HTMLC , que solo puede contener elementos.
3. De manera similar, .childNodespuede contener cualquier nodo porque es una NodeList .
4. Or .innerText. Vea las diferencias aquí o aquí .

Raynos
fuente
3
Sí, IE parece tener algunos problemas: quirksmode.org/dom/w3c_core.html#t71
Felix Kling
44
En realidad, children es una propiedad de la interfaz parentnode, no un elemento. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
victor
Parece que iOS 8.3 (¿quizás otros?) No es compatible .childrencon documentos XML : jsfiddle.net/fbwbjvch/1
Saebekassebil
44
Solo tuve problemas con esto en Microsoft Edge con nodos XML. Parece que a Microsoft Edge no le gustan los niños. Eso es bueno, no me gustaría que ese navegador se reproduzca.
Dan-Nolan
1
Seguimiento natural de "elemento versus nodo": stackoverflow.com/questions/132564/…
user1454265
23

Element.childrensolo devuelve elementos secundarios, mientras que Node.childNodesdevuelve todos los elementos secundarios del nodo . Tenga en cuenta que los elementos son nodos, por lo que ambos están disponibles en los elementos.

Creo que childNodeses más confiable. Por ejemplo, MDC (vinculado anteriormente) señala que IE solo childrenacertó en IE 9. childNodesproporciona menos margen de error por parte de los implementadores del navegador.

Matthew Flaschen
fuente
2
Maldición, si esto funcionara en IE 6-8, sería un sueño hecho realidad.
Ry-
3
@minitech funciona (por algún valor de trabajo). Aparentemente .childrenno filtra los nodos de comentarios, pero filtra los nodos de texto.
Raynos
2
@Raynos: Exactamente, lo mismo con .getElementsByTagName('*'). IE puede ser tan molesto a veces ...
Ry-
Hay implementaciones de shim / polyfill de childrenese soporte IE.
wrlee
7

Buenas respuestas hasta ahora, solo quiero agregar que puede verificar el tipo de nodo usando nodeType:

yourElement.nodeType

Esto le dará un número entero: (tomado de aquí )

| Value |             Constant             |                          Description                          |  |
|-------|----------------------------------|---------------------------------------------------------------|--|
|    1  | Node.ELEMENT_NODE                | An Element node such as <p> or <div>.                         |  |
|    2  | Node.ATTRIBUTE_NODE              | An Attribute of an Element. The element attributes            |  |
|       |                                  | are no longer implementing the Node interface in              |  |
|       |                                  | DOM4 specification.                                           |  |
|    3  | Node.TEXT_NODE                   | The actual Text of Element or Attr.                           |  |
|    4  | Node.CDATA_SECTION_NODE          | A CDATASection.                                               |  |
|    5  | Node.ENTITY_REFERENCE_NODE       | An XML Entity Reference node. Removed in DOM4 specification.  |  |
|    6  | Node.ENTITY_NODE                 | An XML <!ENTITY ...> node. Removed in DOM4 specification.     |  |
|    7  | Node.PROCESSING_INSTRUCTION_NODE | A ProcessingInstruction of an XML document                    |  |
|       |                                  | such as <?xml-stylesheet ... ?> declaration.                  |  |
|    8  | Node.COMMENT_NODE                | A Comment node.                                               |  |
|    9  | Node.DOCUMENT_NODE               | A Document node.                                              |  |
|   10  | Node.DOCUMENT_TYPE_NODE          | A DocumentType node e.g. <!DOCTYPE html> for HTML5 documents. |  |
|   11  | Node.DOCUMENT_FRAGMENT_NODE      | A DocumentFragment node.                                      |  |
|   12  | Node.NOTATION_NODE               | An XML <!NOTATION ...> node. Removed in DOM4 specification.   |  |

Tenga en cuenta que según Mozilla :

Las siguientes constantes han quedado en desuso y ya no deben usarse: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE

Csaba
fuente
0

¡Elegir uno depende del método que estés buscando !?

Iré con ParentNode.children :

Como proporciona un namedItemmétodo que me permite obtener directamente uno de los elementos secundarios sin recorrer todos los elementos secundarios o evitar su uso, getElementByIdetc.

p.ej

ParentNode.children.namedItem('ChildElement-ID'); // JS
ref.current.children.namedItem('ChildElement-ID'); // React
this.$refs.ref.children.namedItem('ChildElement-ID'); // Vue

Iré con Node.childNodes :

Como proporciona forEachmétodo cuando trabajo con, window.IntersectionObserver por ejemplo,

nodeList.forEach((node) => { observer.observe(node) })
// IE11 does not support forEach on nodeList, but easy to be polyfilled.

En Chrome 83

Node.childNodes proporciona entries, forEach, item, keys, lengthyvalues

ParentNode.children proporciona item, lengthynamedItem

Max Ma
fuente