Apa perbedaan antara anak-anak dan anak-anak dalam JavaScript?

305

Saya menemukan diri saya menggunakan JavaScript dan saya berlari melintasi childNodesdan childrenproperti. Saya bertanya-tanya apa perbedaan di antara mereka. Apakah satu lebih disukai dari yang lain?

John
sumber

Jawaban:

330

Memahami bahwa itu .childrenadalah properti dari Elemen . 1 Hanya Elemen yang dimiliki .children, dan anak-anak ini semuanya tipe Element. 2

Namun, .childNodesadalah milik Node . .childNodesdapat berisi simpul apa saja. 3

Contoh nyata adalah:

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

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

Sebagian besar waktu, Anda ingin menggunakan .childrenkarena umumnya Anda tidak ingin mengulang simpul Teks atau Komentar dalam manipulasi DOM Anda.

Jika Anda ingin memanipulasi simpul teks, Anda mungkin menginginkannya .textContent. 4


1. Secara teknis, ini adalah atribut ParentNode , mixin yang disertakan oleh Elemen.
2. Mereka semua elemen karena .childrenmerupakan HTMLCollection , yang hanya dapat berisi elemen.
3. Demikian pula, .childNodesdapat menampung simpul apa pun karena itu adalah NodeList .
4. Atau .innerText. Lihat perbedaannya di sini atau di sini .

Raynos
sumber
3
Ya, IE tampaknya memiliki beberapa masalah: quirksmode.org/dom/w3c_core.html#t71
Felix Kling
4
Sebenarnya, anak-anak adalah properti dari antarmuka parentnode, bukan elemen. usonsci.wordpress.com/2014/09/30/html-children-vs-childnodes
victor
Tampaknya iOS 8.3 (mungkin orang lain?) Tidak mendukung .childrenpada dokumen XML : jsfiddle.net/fbwbjvch/1
Saebekassebil
4
Hanya mengalami masalah dengan ini di Microsoft Edge dengan node XML. Tampaknya Microsoft Edge tidak menyukai anak-anak. Itu bagus, saya tidak ingin browser itu mereproduksi.
Dan-Nolan
1
Tindak lanjut alami "elemen vs. simpul": stackoverflow.com/questions/132564/…
user1454265
23

Element.childrenmengembalikan hanya elemen anak-anak, sementara Node.childNodesmengembalikan semua simpul anak . Perhatikan bahwa elemen adalah simpul, sehingga keduanya tersedia pada elemen.

Saya percaya childNodeslebih dapat diandalkan. Sebagai contoh, MDC (ditautkan di atas) mencatat bahwa IE hanya childrenbenar di IE 9. childNodesmenyediakan lebih sedikit ruang untuk kesalahan oleh pelaksana browser.

Matthew Flaschen
sumber
2
Sial, kalau saja ini bekerja pada IE 6-8, itu akan menjadi mimpi yang menjadi kenyataan.
Ry-
3
@minitech tidak berfungsi (untuk beberapa nilai pekerjaan). Tampaknya .childrentidak memfilter node komentar, tetapi memfilter node teks.
Raynos
2
@ Raynos: Persis - sama dengan .getElementsByTagName('*'). IE kadang-kadang bisa sangat menyebalkan ...
Ry-
Ada implementasi shim / polyfill childrenyang mendukung IE.
mundur
7

Jawaban yang bagus sejauh ini, saya hanya ingin menambahkan bahwa Anda dapat memeriksa jenis simpul menggunakan nodeType:

yourElement.nodeType

Ini akan memberi Anda bilangan bulat: (diambil dari sini )

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

Perhatikan bahwa menurut Mozilla :

Konstanta berikut telah ditinggalkan dan tidak boleh digunakan lagi: Node.ATTRIBUTE_NODE, Node.ENTITY_REFERENCE_NODE, Node.ENTITY_NODE, Node.NOTATION_NODE

Csaba
sumber
0

Pilih satu tergantung pada metode yang Anda cari !?

Saya akan pergi dengan ParentNode.children :

Karena ia menyediakan namedItemmetode yang memungkinkan saya secara langsung untuk mendapatkan salah satu elemen anak-anak tanpa melalui semua anak atau menghindari penggunaan getElementByIddll.

misalnya

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

Saya akan menggunakan Node.childNodes :

Karena menyediakan forEachmetode ketika saya bekerja dengan window.IntersectionObserver misalnya

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

Di Chrome 83

Node.childNodes menyediakan entries, forEach, item, keys, lengthdanvalues

ParentNode.children menyediakan item, lengthdannamedItem

Max Ma
sumber