Quelle est la différence entre les enfants et les nœuds enfant en JavaScript?

305

Je me suis retrouvé à utiliser JavaScript et j'ai parcouru childNodeset childrenpropriétés. Je me demande quelle est la différence entre eux. Est-ce aussi l'un préféré à l'autre?

John
la source

Réponses:

330

Comprenez que .childrenc'est une propriété d'un élément . 1 Seuls les éléments ont .children, et ces enfants sont tous de type élément. 2

Cependant, .childNodesest une propriété de Node . .childNodespeut contenir n'importe quel nœud. 3

Un exemple concret serait:

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 plupart du temps, vous voulez l'utiliser .childrenparce que généralement vous ne voulez pas faire de boucle sur les nœuds Texte ou Commentaire dans votre manipulation DOM.

Si vous souhaitez manipuler des nœuds de texte, vous le souhaitez probablement à la .textContentplace. 4


1. Techniquement, c'est un attribut de ParentNode , un mixin inclus par Element.
2. Ce sont tous des éléments car il .childrens'agit d'une HTMLCollection , qui ne peut contenir que des éléments.
3. De même, .childNodespeut contenir n'importe quel nœud car il s'agit d'une NodeList .
4. Ou .innerText. Voir les différences ici ou ici .

Raynos
la source
3
Ouais, IE semble avoir quelques problèmes: quirksmode.org/dom/w3c_core.html#t71
Felix Kling
4
En fait, les enfants sont une propriété de l'interface parentnode, pas un élément. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
victor
Il semble que iOS 8.3 (peut-être d'autres?) Ne soit pas pris en charge .childrensur les documents XML : jsfiddle.net/fbwbjvch/1
Saebekassebil
4
Seulement eu des problèmes avec cela sur Microsoft Edge avec des nœuds XML. Il semble que Microsoft Edge n'aime pas les enfants. C'est bien, je ne voudrais pas que ce navigateur se reproduise.
Dan-Nolan
1
Suivi naturel de "élément vs nœud": stackoverflow.com/questions/132564/…
user1454265
23

Element.childrenrenvoie uniquement les enfants des éléments , tandis que Node.childNodesrenvoie tous les enfants des nœuds . Notez que les éléments sont des nœuds, donc les deux sont disponibles sur les éléments.

Je pense que childNodesc'est plus fiable. Par exemple, MDC (lié ci-dessus) note qu'IE ne fonctionne que childrendans IE 9. childNodesoffre moins de marge d'erreur aux implémenteurs de navigateur.

Matthew Flaschen
la source
2
Darn, si seulement cela fonctionnait sur IE 6-8, ce serait un rêve devenu réalité.
Ry-
3
@minitech ça marche (pour une certaine valeur de travail). Apparemment, .childrenil ne filtre pas les nœuds de commentaire, mais il filtre les nœuds de texte.
Raynos
2
@Raynos: Exactement - pareil avec .getElementsByTagName('*'). IE peut être si ennuyeux parfois ...
Ry-
Il existe des implémentations shim / polyfill childrenqui prennent en charge IE.
wrlee
7

De bonnes réponses jusqu'à présent, je veux seulement ajouter que vous pouvez vérifier le type d'un nœud en utilisant nodeType:

yourElement.nodeType

Cela vous donnera un entier: (extrait d' ici )

| 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.   |  |

Notez que selon Mozilla :

Les constantes suivantes sont obsolètes et ne doivent plus être utilisées: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE

Csaba
la source
0

Choisissez-en un dépend de la méthode que vous recherchez!?

J'irai avec ParentNode.children :

Comme il fournit une namedItemméthode qui me permet d'obtenir directement l'un des éléments enfants sans parcourir tous les enfants ou éviter d'utiliser getElementByIdetc.

par exemple

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

J'irai avec Node.childNodes :

Comme il fournit une forEachméthode lorsque je travaille avec window.IntersectionObserver par exemple

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

Sur Chrome 83

Node.childNodes fournit entries, forEach, item, keys, lengthetvalues

ParentNode.children fournit item, lengthetnamedItem

Max Ma
la source