Ich habe eine Javascript-Funktion, die eine Liste von HTML-Knoten akzeptiert, aber ein Javascript-Array erwartet (es werden einige Array-Methoden ausgeführt), und ich möchte ihr die Ausgabe zuführen, die Document.getElementsByTagName
eine DOM-Knotenliste zurückgibt.
Anfangs dachte ich daran, etwas Einfaches zu verwenden wie:
Array.prototype.slice.call(list,0)
Und das funktioniert in allen Browsern einwandfrei, außer natürlich Internet Explorer, der den Fehler "JScript-Objekt erwartet" zurückgibt, da die von Document.getElement*
Methoden zurückgegebene DOM-Knotenliste anscheinend kein JScript-Objekt ist, das ausreicht, um das Ziel eines Funktionsaufrufs zu sein.
Vorsichtsmaßnahmen: Es macht mir nichts aus, Internet Explorer-spezifischen Code zu schreiben, aber ich darf keine Javascript-Bibliotheken wie JQuery verwenden, da ich ein Widget schreibe, das in die Website eines Drittanbieters eingebettet werden soll, und ich kann keine externen Bibliotheken laden schafft Konflikte für die Kunden.
Meine letzte Anstrengung besteht darin, die DOM-Knotenliste zu durchlaufen und selbst ein Array zu erstellen. Aber gibt es eine bessere Möglichkeit, dies zu tun?
quelle
Antworten:
Nodelisten sind Host - Objekte , die unter Verwendung
Array.prototype.slice
wird Verfahren auf Host - Objekten nicht garantiert werden , stellt die ECMAScript - Spezifikation:Ich würde Ihnen empfehlen, eine einfache Funktion zu erstellen, um das zu durchlaufen
NodeList
und jedes vorhandene Element einem Array hinzuzufügen:AKTUALISIEREN:
Wie andere Antworten vermuten lassen, können Sie jetzt in modernen Umgebungen die Spread-Syntax oder die
Array.from
Methode verwenden:Aber wenn ich darüber nachdenke, denke ich, dass der häufigste Anwendungsfall zum Konvertieren einer NodeList in ein Array darin besteht, darüber zu iterieren, und jetzt hat das
NodeList.prototype
Objekt dieforEach
Methode nativ . Wenn Sie sich also in einer modernen Umgebung befinden, können Sie sie direkt verwenden oder haben eine Pollyfill.quelle
array[i] = obj[i]
stattdessen tunarray.push(obj[i])
?obj.length
etwas anderes als ein ganzzahliger Wert?In es6 können Sie einfach Folgendes verwenden:
Spread-Operator
Verwenden von
Array.from
Weitere Informationen finden Sie unter https://developer.mozilla.org/en-US/docs/Web/API/NodeList
quelle
Array.from()
: DArray.from
funktioniert dies nur , da TS dies auf transpiliertnodelist.slice
- was nicht unterstützt wird.Array.from
spread
verwendet wird.Mit Spread (ES2015) ist es so einfach wie:
[...document.querySelectorAll('p')]
(Optional: Verwenden Sie Babel, um den obigen ES6-Code in die ES5-Syntax zu transpilieren.)
Probieren Sie es in der Konsole Ihres Browsers aus und sehen Sie die Magie:
quelle
Verwenden Sie diesen einfachen Trick
quelle
Array.prototype.slice
(oder[].slice
wie Sie sagen)? Als Hinweis möchte ich kommentieren, dass der IE-spezifische Fehler, den ich im Q dokumentiert habe, in IE 8 oder niedriger auftritt, wo ermap
sowieso nicht implementiert ist. In IE 9 ("Standardmodus") oder höher sind beideslice
undmap
auf die gleiche Weise erfolgreich.Obwohl es sich nicht wirklich um eine richtige Unterlegscheibe handelt, da es keine Spezifikation gibt, die das Arbeiten mit DOM-Elementen erfordert, habe ich eine erstellt, die Sie auf
slice()
diese Weise verwenden können: https://gist.github.com/brettz9/6093105UPDATE : Als ich dies mit dem Editor der DOM4-Spezifikation angesprochen habe (mit der Frage, ob sie Host-Objekten ihre eigenen Einschränkungen hinzufügen könnten (damit die Spezifikation erfordert, dass Implementierer diese Objekte ordnungsgemäß konvertieren, wenn sie mit Array-Methoden verwendet werden), die über die ECMAScript-Spezifikation hinausgehen Er antwortete, dass "Host-Objekte gemäß ES6 / IDL mehr oder weniger veraltet sind". Ich sehe per http://www.w3.org/TR/WebIDL/#es-array, dass Spezifikationen diese IDL verwenden können, um "Plattform-Array-Objekte" zu definieren, aber http://www.w3.org/TR/domcore/ nicht Es scheint, dass die neue IDL nicht für verwendet wird
HTMLCollection
(obwohl es so aussieht, als ob dies der Fall wäre,Element.attributes
obwohl nur explizit angegeben wird, dass WebIDL für DOMString und DOMTimeStamp verwendet wird). Ich verstehe[ArrayClass]
(das von Array.prototype erbt) wird für verwendetNodeList
(undNamedNodeMap
ist jetzt zugunsten des einzigen Elements, das es noch verwenden würde, veraltetElement.attributes
). In jedem Fall sieht es so aus, als ob es Standard werden soll. Der ES6 istArray.from
möglicherweise auch für solche Konvertierungen praktischer als die AngabeArray.prototype.slice
und semantisch klarer als[].slice()
(und die kürzere FormArray.slice()
(ein "Array-Generikum") ist meines Wissens nicht zum Standardverhalten geworden).quelle
Heute, im Jahr 2018, könnten wir ECMAScript 2015 (6. Ausgabe) oder ES6 verwenden, aber nicht alle Browser können es verstehen (z. B. versteht IE nicht alles). Wenn Sie möchten, können Sie ES6 wie folgt verwenden:
var array = [... NodeList];
( als Spread-Operator ) odervar array = Array.from(NodeList);
.In einem anderen Fall (wenn Sie ES6 nicht verwenden können) können Sie den kürzesten Weg verwenden, um a
NodeList
in ein zu konvertierenArray
:var array = [].slice.call(NodeList, 0);
.Beispielsweise:
Aber wenn Sie die iterieren
DOM
nur leicht Knotenliste, dann brauchen Sie nicht ein konvertieren ,NodeList
um eineArray
. Es ist möglich, die Elemente in einerNodeList
Verwendung zu durchlaufen:Versuchen Sie nicht, die Elemente in der Liste zu verwenden
for...in
oderfor each...in
aufzulisten, da dies auch die Länge und die Elementeigenschaften von auflistetNodeList
und Fehler verursacht, wenn Ihr Skript davon ausgeht, dass es sich nur um Elementobjekte handelt. Esfor..in
ist auch nicht garantiert, die Immobilien in einer bestimmten Reihenfolge zu besuchen.for...of
Schleifen durchlaufen NodeList-Objekte korrekt.Auch sehen:
quelle
Dies sollte funktionieren, browserübergreifend sein und Ihnen alle "Element" -Knoten bringen.
quelle