Durchlaufen Sie childNodes


83

Ich versuche, childNodes wie folgt zu durchlaufen:

var children = element.childNodes;
children.forEach(function(item){
    console.log(item);
});

Es wird jedoch Uncaught TypeError: undefined is not a functionaufgrund der forEachFunktion ausgegeben . Ich versuche auch zu verwenden , childrenanstatt childNodesaber nichts geändert.

Weiß jemand was los ist?

Antworten:


121

Die Variable childrenist eine NodeListInstanz und NodeLists sind nicht wahr Arrayund erben daher die forEachMethode nicht.

Auch einige Browser unterstützen es tatsächlich nodeList.forEach


ES5

Sie können slicevon verwenden Array, um das NodeListin ein richtiges umzuwandeln Array.

var array = Array.prototype.slice.call(children);

Sie können es auch einfach verwenden call, um forEaches NodeListals Kontext aufzurufen und zu übergeben .

[].forEach.call(children, function(child) {});


ES6

Sie können die fromMethode verwenden, um Ihre NodeListin eine zu konvertieren Array.

var array = Array.from(children);

Oder Sie können auch die Spread-Syntax... wie folgt verwenden

let array = [ ...children ];


Ein Hack, der verwendet werden kann, ist NodeList.prototype.forEach = Array.prototype.forEachund Sie können ihn dann forEachmit jedem verwenden, NodeListohne sie jedes Mal konvertieren zu müssen.

NodeList.prototype.forEach = Array.prototype.forEach
var children = element.childNodes;
children.forEach(function(item){
    console.log(item);
});

Eine ausführliche Erklärung und andere Möglichkeiten finden Sie unter Ein umfassender Einblick in NodeLists, Arrays, Konvertieren von NodeLists und Verstehen des DOM .


Wie könnte ich NodeList in ein reines Array konvertieren?
user3828771

Mit Beispiel aktualisiert, aber lesen Sie den Link, den ich gepostet habe, erklärt alles :)
GillesC

2
Alternativ können Sie dies tun:[].forEach.call(element.childNodes, child => console.log(child))
XåpplI'-I0llwlg'I -

2
Noch cooler es6 Weg: let items = [ ...children ]wird es in ein Array
verwandeln

2
Das Anwenden von Array-Methoden auf NodeLists ist ein großes Problem: NodeLists wie node.childNodes sind Live-Listen. Wenn Sie das DOM während Ihrer Schleife bearbeiten, kann sich die NodeList ändern, sodass der Rückruf an forEach () nicht aufgerufen wird Jedes Element der Liste - oder mehr Elemente als ursprünglich in der Liste enthalten - führt zu unvorhersehbaren Ergebnissen. Es ist vorzuziehen, eine NodeList in ein Array umzuwandeln, bevor Sie sie durchlaufen.
Stephband

30

Ich bin sehr spät zur Party, aber seitdem element.lastChild.nextSibling === nullscheint mir Folgendes die einfachste Option zu sein:

for(var child=element.firstChild; child!==null; child=child.nextSibling) {
    console.log(child);
}

1
Die einfachste Option ist die Verwendung einer regulären "for" -Schleife. Aber Ihre Option ist interessant.
Kirill Reznikov

Ich mag das am besten, hatte vor, dasselbe zu implementieren. Logisch und ohne Konvertierungen
Ujjwal Singh

23

Hier ist, wie Sie es mit for-inSchleife tun können .

var children = element.childNodes;

for(child in children){
    console.log(children[child]);
}

14
Sie haben die Überprüfung vergessen: if (children.hasOwnProperty (child)) {// hier codieren} oder Sie werden über unerwünschte Requisiten wie "Länge" usw. iterieren!
Kirill Reznikov

7
Noch besser: Verwenden for ... of ...Sie jedoch die ES6-Syntax.
Jespertheend

4

Versuchen Sie es mit forSchleife. Es gibt einen Fehler, forEachda es sich um eine Sammlung von Knoten handelt nodelist.

Oder dies sollte die Knotenliste in ein Array konvertieren

function toArray(obj) {
  var array = [];
  for (var i = 0; i < obj.length; i++) { 
    array[i] = obj[i];
  }
return array;
}

Oder Sie können dies verwenden

var array = Array.prototype.slice.call(obj);

4

Konnte nicht widerstehen, eine andere Methode mit hinzuzufügen childElementCount. Es gibt die Anzahl der untergeordneten Elementknoten eines bestimmten übergeordneten Elements zurück, sodass Sie eine Schleife darüber durchführen können.

for(var i=0, len = parent.childElementCount ; i < len; ++i){
    ... do something with parent.children[i]
    }

3
const results = Array.from(myNodeList.values()).map(parser_item);

NodeList ist kein Array, aber NodeList.values ​​() gibt einen Array-Iterator zurück und kann ihn in Array konvertieren.


2

Versuchen Sie dies [Durchquerung in umgekehrter Reihenfolge]:

var childs = document.getElementById('parent').childNodes;
var len = childs.length;
if(len --) do {
    console.log('node: ', childs[len]);
} while(len --);

ODER [in der Reihenfolge Durchquerung]

var childs = document.getElementById('parent').childNodes;
var len = childs.length, i = -1;
if(++i < len) do {
    console.log('node: ', childs[i]);
} while(++i < len);

Die einfache for-Schleife ist besser lesbar als die while-Schleife. Der Autor fragt nicht nach der umgekehrten / umgekehrten Reihenfolge.
Kirill Reznikov

2

Hier ist eine funktionale ES6-Methode zum Iterieren über a NodeList. Diese Methode nutzt die Array‚s in forEachetwa so:

Array.prototype.forEach.call(element.childNodes, f)

Wo fist die Iteratorfunktion, die einen untergeordneten Knoten als ersten Parameter und den Index als zweiten empfängt?

Wenn Sie NodeLists mehrmals durchlaufen müssen, können Sie daraus eine kleine funktionale Dienstprogrammmethode erstellen:

const forEach = f => x => Array.prototype.forEach.call(x, f);

// For example, to log all child nodes
forEach((item) => { console.log(item); })(element.childNodes)

// The functional forEach is handy as you can easily created curried functions
const logChildren = forEach((childNode) => { console.log(childNode); })
logChildren(elementA.childNodes)
logChildren(elementB.childNodes)

(Sie können den gleichen Trick für map()und andere Array-Funktionen ausführen.)


0

Wenn Sie so etwas häufig tun, lohnt es sich möglicherweise, die Funktion selbst zu definieren.

if (typeof NodeList.prototype.forEach == "undefined"){
    NodeList.prototype.forEach = function (cb){
        for (var i=0; i < this.length; i++) {
            var node = this[i];
            cb( node, i );
        }
    };
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.