Filtern oder Zuordnen von Knotenlisten in ES6

87

Was ist der effizienteste Weg, um eine Knotenliste in ES6 zu filtern oder zuzuordnen?

Basierend auf meinen Messwerten würde ich eine der folgenden Optionen verwenden:

[...nodelist].filter

oder

Array.from(nodelist).filter

Welches würdest du empfehlen? Und gibt es bessere Möglichkeiten, zum Beispiel ohne Arrays?

Christophe
quelle
2
Grundsätzlich machen beide Methoden dasselbe. Wenn Sie es verwenden babel, [...coll]fordern Sie einfach Array.from(coll)alles an, was kein ist Array.
Leonid Beschastny
FWIW, die ...Syntax wird möglicherweise von älteren IDEs nicht unterstützt, obwohl dies Array.from()nur eine reguläre Methode ist.
Marat Tanalin

Antworten:

126
  • [...nodelist] macht ein Array aus einem Objekt, wenn das Objekt iterierbar ist.
  • Array.from(nodelist)macht ein Array aus einem Objekt, wenn das Objekt iterierbar ist oder wenn das Objekt Array-ähnlich ist (hat .lengthund numerische Requisiten)

Ihre beiden Beispiele sind identisch, falls NodeList.prototype[Symbol.iterator]vorhanden, da beide Fälle iterable abdecken. Wenn Ihre Umgebung nicht so konfiguriert wurde, dass sie NodeListiteriert werden kann, schlägt Ihr erstes Beispiel fehl und das zweite ist erfolgreich. behandelt diesen FallBabel derzeit nicht richtig .

Wenn Ihr NodeListalso iterierbar ist, liegt es wirklich an Ihnen, was Sie verwenden. Ich würde wahrscheinlich von Fall zu Fall wählen. Ein Vorteil davon Array.fromist, dass ein zweites Argument einer Zuordnungsfunktion erforderlich ist, während das erste [...iterable].map(item => item)ein temporäres Array erstellen Array.from(iterable, item => item)müsste , dies jedoch nicht. Wenn Sie die Liste jedoch nicht zuordnen, spielt dies keine Rolle.

loganfsmyth
quelle
17

TL; DR;

Array.prototype.slice.call(nodelist).filter

Die Slice () -Methode gibt ein Array zurück. Das zurückgegebene Array ist eine flache Kopie der Sammlung (NodeList). Es funktioniert also schneller als Array.from (). Es funktioniert also genauso schnell wie Array.from ()

Elemente der ursprünglichen Sammlung werden wie folgt in das zurückgegebene Array kopiert:

  • Bei Objektreferenzen (und nicht dem eigentlichen Objekt) kopiert Slice Objektreferenzen in das neue Array. Sowohl das ursprüngliche als auch das neue Array beziehen sich auf dasselbe Objekt. Wenn sich ein referenziertes Objekt ändert, sind die Änderungen sowohl für das neue als auch für das ursprüngliche Array sichtbar.
  • Bei Zeichenfolgen, Zahlen und Booleschen Werten (nicht String-, Zahlen- und Booleschen Objekten) kopiert Slice die Werte in das neue Array. Änderungen an der Zeichenfolge, Zahl oder dem Booleschen Wert in einem Array wirken sich nicht auf das andere Array aus.

Kurze Erklärung zu den Argumenten

Array.prototype.slice (beginIndex, endIndex)

  • Nimmt optionale Argumente beginIndex und endIndex. Wenn sie nicht bereitgestellt werden, verwendet Slices beginIndex == 0 und extrahiert somit alle Elemente aus der Sammlung

Array.prototype.slice.call (Namespace, beginIndex, endIndex)

  • nimmt ein Objekt als erstes Argument. Wenn wir eine Sammlung als Objekt verwenden, bedeutet dies wörtlich, dass wir die Slice-Methode direkt von diesem Objekt- Namespace aufrufen. Slice ()
Serge Seletskyy
quelle
2
Vielen Dank für dieses Code-Snippet, das möglicherweise nur begrenzte, sofortige Hilfe bietet. Eine richtige Erklärung würde ihren langfristigen Wert erheblich verbessern, indem sie zeigt, warum dies eine gute Lösung für das Problem ist, und es für zukünftige Leser mit anderen, ähnlichen Fragen nützlicher machen. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen, einschließlich der von Ihnen getroffenen Annahmen.
Maximilian Peters
Ich frage mich, ob dies IE-Unterstützung hat, da Array.fromdies nicht der Fall ist. Zeit, eine IE-Maschine zu finden. Jetzt bin ich wirklich verwirrt, weil ich Array.from in IE10 und IE11 verwenden konnte: \. Diese Methode funktioniert in IE10 + 11, aber Array.from funktioniert nicht, wenn in der gesamten Dokumentation etwas anderes angegeben ist.
CTS_AE
Array.fromfunktioniert nicht für mich in IE11 Objekt unterstützt keine Eigenschaft oder Methode 'von'
Fus Ro Dah
Vielen Dank, dies funktionierte für mich bei einer alten Implementierung von JavaScript
Vic Seedoubleyew
1
Array.fromGibt auch eine flache Kopie zurück. Ich verstehe also nicht, wie Sie zu dem Schluss kommen, dass es schneller funktioniert als Array#slice.
Robert
9

Ich habe eine Referenz gefunden , die mapdirekt in der NodeList von verwendet wird

Array.prototype.map.call(nodelist, fn)

Ich habe es nicht getestet, aber es scheint plausibel, dass dies schneller sein würde, da es direkt auf die NodeList zugreifen sollte.

Goweon
quelle
2

Wie wäre es damit:

// Be evil. Extend the prototype.
if (window.NodeList && !NodeList.prototype.filter) {
  NodeList.prototype.filter = Array.prototype.filter;
}

// Use it like you'd expect:
const noClasses = document
  .querySelectorAll('div')
  .filter(div => div.classList.length === 0)

Es ist der gleiche Ansatz wie in den MDN-Dokumenten für NodeList.forEach (unter 'Polyfill') erwähnt. Er funktioniert für IE11 , Edge, Chrome und FF.

Panepeter
quelle