Яка різниця між дітьми та дочірніми вузлами в JavaScript?


305

Я знайшов себе за допомогою JavaScript, і я наткнувся на childNodesта childrenвластивості. Мені цікаво, в чому різниця між ними. Також один віддає перевагу іншому?

Відповіді:


330

Зрозумійте, що .childrenце властивість елемента . 1 Є лише Елементи .children, і всі ці діти - Елемент типу. 2

Однак .childNodesце властивість Node . .childNodesможе містити будь-який вузол. 3

Конкретним прикладом може бути:

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

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

Більшу частину часу ви хочете використовувати, .childrenтому що, як правило, ви не хочете перебирати вузли Текст чи коментар під час маніпуляції з DOM.

Якщо ви хочете маніпулювати текстовими вузлами, ви, мабуть, хочете .textContentзамість цього. 4


1. Технічно це атрибут ParentNode , міксину , включеного Element.
2. Всі вони є елементами, оскільки .childrenце HTMLCollection , який може містити лише елементи.
3. Аналогічно, .childNodesможе містити будь-який вузол, оскільки це NodeList .
4. Або .innerText. Дивіться відмінності тут або тут .


3
Так, у IE, здається, є деякі проблеми: quirksmode.org/dom/w3c_core.html#t71
Фелікс Клінг

4
Насправді діти є властивістю інтерфейсу батьківського вузла, а не елемента. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
переможець

Здається, iOS 8.3 (можливо, інші?) Не підтримує .childrenдокументи XML : jsfiddle.net/fbwbjvch/1
Saebekassebil

4
Проблеми з цим виникли лише в Microsoft Edge з XML-вузлами. Здається, Microsoft Edge не любить дітей. Це добре, я б не хотів, щоб цей браузер відтворював.
Дан-Нолан

1
Природне спостереження за «елемента проти вузла»: stackoverflow.com/questions/132564 / ...
user1454265

23

Element.childrenповертає лише дітей- елементів , тоді як Node.childNodesповертає всіх дітей- вузлів . Зауважте, що елементи - це вузли, тому обидва доступні для елементів.

Я вважаю, childNodesце надійніше. Наприклад, MDC (пов'язаний вище) зазначає, що IE отримав тількиchildren право в IE 9. childNodesнадає менше можливостей для помилок з боку браузерних реалізаторів.


2
Дарн, якби тільки це працювало на IE 6-8, це було б мрією.
Ри-

3
@minitech це працює (для деякої цінності роботи). Мабуть .children, не фільтрує вузли коментарів, але він фільтрує текстові вузли.
Райнос

2
@Raynos: Точно - те ж саме і з .getElementsByTagName('*'). IE може бути настільки дратівливим часом ...
Ry-

Є реалізація shim / polyfill, childrenщо підтримує IE.
wrlee

7

Хороші відповіді поки що, хочу лише додати, що ви можете перевірити тип вузла, використовуючи nodeType:

yourElement.nodeType

Це дасть вам ціле число: (взято звідси )

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

Зауважте, що згідно Mozilla :

Наступні константи застаріли і більше не повинні використовуватися: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE


0

Вибір одного залежить від способу, який ви шукаєте !?

Я піду з ParentNode.children :

Оскільки він пропонує namedItemметод, який дозволяє мені безпосередньо отримати один із дочірніх елементів, не переглядаючи всіх дітей або уникаючи використанняgetElementById тощо.

напр

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

Я піду з Node.childNodes :

Оскільки це забезпечує forEachметод, коли я працюю, window.IntersectionObserver наприклад

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

На Chrome 83

Node.childNodes забезпечує entries, forEach, item, keys, lengthіvalues

ParentNode.children забезпечує item, lengthіnamedItem

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.