Qual é a diferença entre children e childNodes em JavaScript?

305

Eu encontrei-me usando JavaScript e eu corri em toda childNodese childrenpropriedades. Eu estou querendo saber qual é a diferença entre eles. Também é um preferido para o outro?

John
fonte

Respostas:

330

Entenda que .childrené uma propriedade de um elemento . 1 Somente Elements possuem .children, e esses filhos são do tipo Element. 2

No entanto, .childNodesé uma propriedade do Node . .childNodespode conter qualquer nó. 3

Um exemplo concreto seria:

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

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

Na maioria das vezes, você deseja usar .childrenporque geralmente não deseja fazer um loop sobre nós de texto ou comentário na manipulação do DOM.

Se você deseja manipular nós de texto, provavelmente deseja .textContent. 4


1. Tecnicamente, é um atributo do ParentNode , um mixin incluído pelo Element.
2. Eles são todos elementos porque .childrené um HTMLCollection , que pode conter apenas elementos.
3. Da mesma forma, .childNodespode conter qualquer nó porque é um NodeList .
4. Or .innerText. Veja as diferenças aqui ou aqui .

Raynos
fonte
3
Sim, IE parece ter alguns problemas: quirksmode.org/dom/w3c_core.html#t71
Felix Kling
4
Na verdade, children é uma propriedade da interface do nó pai, não um elemento. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
vencedor
Parece iOS 8.3 (talvez outros?) Não suporta .childrenem documentos XML : jsfiddle.net/fbwbjvch/1
Saebekassebil
4
Só tive problemas com isso no Microsoft Edge com nós XML. Parece que o Microsoft Edge não gosta de crianças. Isso é bom, eu não gostaria que o navegador fosse reproduzido.
21316 Dan-Nolan
1
Seguimento natural de "elemento x nó": stackoverflow.com/questions/132564/…
user1454265
23

Element.childrenretorna apenas filhos do elemento , enquanto Node.childNodesretorna todos os filhos do . Observe que os elementos são nós, portanto, ambos estão disponíveis nos elementos.

Eu acredito que childNodesé mais confiável. Por exemplo, o MDC (vinculado acima) observa que o IE só acertou childrenno IE 9. childNodesfornece menos espaço para erros por implementadores de navegador.

Matthew Flaschen
fonte
2
Droga, se isso funcionasse no IE 6-8, seria um sonho tornado realidade.
Ry-
3
@minitech funciona (para algum valor do trabalho). Aparentemente .children, não filtra nós de comentários, mas filtra nós de texto.
Raynos 28/10/11
2
@ Raynos: Exatamente - o mesmo com .getElementsByTagName('*'). IE pode ser tão irritante às vezes ...
Ry-
Existem implementações shim / polyfill childrendesse suporte ao IE.
wrlee
7

Boas respostas até agora, quero apenas acrescentar que você pode verificar o tipo de um nó usando nodeType:

yourElement.nodeType

Isso fornecerá um número inteiro: (extraído daqui )

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

Observe que, de acordo com o Mozilla :

As seguintes constantes foram descontinuadas e não devem mais ser usadas: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE

Csaba
fonte
0

Escolha um depende do método que você está procurando !?

Eu irei com ParentNode.children :

Como ele fornece um namedItemmétodo que me permite obter diretamente um dos elementos filhos sem repetir todos os filhos ou evitar o uso getElementByIdetc.

por exemplo

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

Eu irei com Node.childNodes :

Como ele fornece forEachmétodo quando eu trabalho com, window.IntersectionObserver por exemplo,

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

No Chrome 83

Node.childNodes fornece entries, forEach, item, keys, lengthevalues

ParentNode.children fornece item, lengthenamedItem

Max Ma
fonte