Il modo migliore per ottenere i nodes figlio

Mi stavo chiedendo, JavaScript offre una varietà di metodi per ottenere il primo elemento figlio da qualsiasi elemento, ma qual è il migliore? Nel migliore dei casi, intendo: la maggior parte dei browser compatibili, più veloce, più completa e prevedibile in termini di comportamento. Un elenco di metodi / proprietà che uso come alias:

var elem = document.getElementById('container'); var child = elem.children[0]; var child = elem.firstElementChild; // == children[0] 

Questo funziona per entrambi i casi:

 var child = elem.childNodes[0]; // or childNodes[1], see below 

Questo è in caso di moduli, o

iterazione. Se potessi incontrare elementi di testo:

 var child = elem.childNodes; // treat as NodeList var child = elem.firstChild; 

Per quanto posso capire, firstChild usa NodeList da childNodes, e firstElementChild usa i children . Sto basando questa ipotesi sul riferimento MDN:

childNode è un riferimento al primo elemento figlio del nodo elemento o null se non ce n’è uno.

Immagino che, in termini di velocità, la differenza, se presente, sarà prossima a nulla, poiché firstElementChild è effettivamente un riferimento ai children[0] , e l’object children è già in memoria comunque.

Quello che mi lancia, è l’object childNodes . L’ho usato per dare un’occhiata a un modulo, in un elemento tabella. Mentre i children elencano tutti gli elementi del modulo, anche childNodes sembra includere spazi bianchi dal codice HTML:

 console.log(elem.childNodes[0]); console.log(elem.firstChild); 

Entrambi log

 console.log(elem.childNodes[1]); console.log(elem.children[0]); console.log(elem.firstElementChild); 

Tutti i log <input type="text"> . Come mai? Capirei che un object mi permetterebbe di lavorare con il codice HTML “grezzo”, mentre l’altro si attacca al DOM, ma l’elemento childNodes sembra funzionare su entrambi i livelli.

Per tornare alla mia domanda iniziale, la mia ipotesi sarebbe: se voglio l’object più completo, childNodes è la strada da percorrere, ma a causa della sua completezza, potrebbe non essere il più prevedibile in termini di ritorno dell’elemento che voglio / aspettati in ogni momento. Anche il supporto cross-browser potrebbe rivelarsi una sfida in quel caso, anche se potrei sbagliarmi.

Qualcuno potrebbe chiarire la distinzione tra gli oggetti a portata di mano? Se c’è una differenza di velocità, per quanto trascurabile, mi piacerebbe saperlo anche io. Se vedo tutto sbagliato, sentiti libero di educarmi.


PS: Per favore, per favore, mi piace JavaScript, quindi sì, voglio occuparmi di questo genere di cose. Risposte come “jQuery si occupa di questo per te” non sono ciò che sto cercando, quindi nessun tag jquery .

Sembra che tu stia pensando troppo. Hai osservato la differenza tra childNodes e children , ovvero che childNodes contiene tutti i nodes, inclusi i nodes di testo costituiti interamente da spazi bianchi, mentre i children sono una raccolta di soli nodes figlio che sono elementi. Questo è davvero tutto quello che c’è da fare.

Non c’è nulla di imprevedibile in entrambe le raccolte, anche se ci sono un paio di problemi da conoscere:

  • IE <= 8 non include nodi di testo di solo spazio bianco in childNodes mentre altri browser lo fanno
  • IE <= 8 include i nodi di commento all'interno dei children mentre altri browser hanno solo elementi

children , firstElementChild e gli amici sono solo convenienze, presentando una vista filtrata del DOM limitato ai soli elementi.

firstElementChild potrebbe non essere disponibile in IE <9 (solo firstChild)

su IE <9 firstChild è il primo Elemento figlio perché MS DOM (IE <9) non memorizza nodi di testo vuoti. Ma se lo fai su altri browser restituiranno nodi di testo vuoti ...

la mia soluzione

child=(elem.firstElementChild||elem.firstChild)

questo darà il primo figlio anche su IE <9

Il modo cross-browser per fare è utilizzare i childNodes per ottenere NodeList , quindi creare una matrice di tutti i nodes con nodeType ELEMENT_NODE .

 /** * Return direct children elements. * * @param {HTMLElement} * @return {Array} */ function elementChildren (element) { var childNodes = element.childNodes, children = [], i = childNodes.length; while (i--) { if (childNodes[i].nodeType == 1) { children.unshift(childNodes[i]); } } return children; } 

http://jsfiddle.net/s4kxnahu/

Questo è particolarmente facile se si utilizza una libreria di utilità come lodash :

 /** * Return direct children elements. * * @param {HTMLElement} * @return {Array} */ function elementChildren (element) { return _.where(element.childNodes, {nodeType: 1}); } 

Futuro:

È ansible utilizzare querySelectorAll in combinazione con :scope pseudo-class (corrisponde all’elemento che è il punto di riferimento del selettore):

 parentElement.querySelectorAll(':scope > *'); 

Al momento della stesura di questo :scope è supportato in Chrome, Firefox e Safari.

Ehi ragazzi non lasciatevi ingannare dallo spazio bianco. basta testarlo in un browser console. usa nativo javascript. Ecco ed esempio con due set “ul” con la stessa class. Non è necessario avere il tuo elenco ‘ul’ tutto in una riga per evitare lo spazio bianco basta usare il numero di array per saltare oltre lo spazio bianco.

Come aggirare lo spazio bianco con querySelector() then childNodes[] js fiddle link: https://jsfiddle.net/aparadise/56njekdo/

 var y = document.querySelector('.list'); var myNode = y.childNodes[11].style.backgroundColor='red'; 
  • 8
  • 9
  • 100
  • ABC
  • DEF
  • XYZ

Giusto per aggiungere alle altre risposte, ci sono ancora delle differenze degne di nota qui, in particolare quando si tratta di elementi .

Ho usato entrambi .childNodes e .children e ho preferito lavorare con HTMLCollection fornito dal getter .children .

Oggi, tuttavia, ho .children problemi con IE / Edge in caso di errore durante l’utilizzo di .children su un . Mentre .children è supportato in IE su elementi HTML di base, non è supportato su frammenti documento / documento o elementi SVG .

Per me, sono stato in grado di catturare semplicemente gli elementi necessari tramite .childNodes[n] perché non ho nodes di testo estranei di cui preoccuparsi. Potresti essere in grado di fare lo stesso, ma come detto sopra, non dimenticare che potresti imbatterti in elementi inaspettati.

Spero che questo sia utile a qualcuno che si gratta la testa cercando di capire perché. I .children lavorano altrove nel loro js su IE moderno e non riescono su elementi di documento o SVG.