Ich bin auf diese nette Verknüpfung gestoßen, um eine DOM-Knotenliste in ein reguläres Array zu konvertieren, aber ich muss zugeben, ich verstehe nicht ganz, wie es funktioniert:
[].slice.call(document.querySelectorAll('a'), 0)
Es beginnt also mit einem leeren Array []
und wird dann slice
verwendet, um das Ergebnis von call
in ein neues Array umzuwandeln. Ja?
Das bisschen, das ich nicht verstehe, ist das call
. Wie wird das document.querySelectorAll('a')
von einer NodeList in ein reguläres Array konvertiert ?
javascript
arrays
call
slice
Yansky
quelle
quelle
Array.prototype.slice.call(document.querySelectorAll('a'));
ist eine richtige Methode, um den von Ihnen geschriebenen Codeabschnitt zu schreiben.Array.from
. Dies würde beispielsweise dasselbe tun: Array.from (document.querySelectorAll ('a'));Antworten:
Was hier passiert ist, dass Sie aufrufen,
slice()
als ob es eine Funktion derNodeList
Verwendung wärecall()
. Wasslice()
tut in diesem Fall ist ein leeres Array zu erstellen, dann Iterierte durch das Objekt es läuft auf (ursprünglich ein Array, ein jetztNodeList
) und halten Sie die Elemente dieses Objekts in das leere Array anhängt es erstellt, die schließlich zurückgeführt wird. Hier ist ein Artikel dazu .BEARBEITEN:
Das ist nicht richtig.
[].slice
gibt ein Funktionsobjekt zurück. Ein Funktionsobjekt hat eine Funktion,call()
die die Funktion aufruft, die den ersten Parameter voncall()
to zuweistthis
. Mit anderen Worten, die Funktion denkt, dass sie vom Parameter (der vonNodeList
zurückgegeben wirddocument.querySelectorAll('a')
) und nicht von einem Array aufgerufen wird .quelle
Array.prototype.slice.call(...)
, tatsächlich ein Array-Objekt ([]
) instanziiert, nur um auf seine Prototyp-Slice-Methode zuzugreifen. Das ist eine verschwendete Instanziierung.Array.prototype.slice.call(...)
Stattdessen zu sagen ist sauberer, obwohl Sie Ihrem JS mehrere Zeichen hinzufügen, wenn Sie zählen ...NodeList
s[]
ist zuverlässiger, daArray
es zu etwas anderem überschrieben werden könnte. Wenn Sie es wiederverwenden müssenArray#slice
, ist es eine gute Idee, es zwischenzuspeichern.var array = []; var push = array.push; var slice = array.slice; var splice = array.splice;
Tut er dies für das Sicherheitsproblem, das @MathiasBynens erwähnt?In JavaScript können Methoden eines Objekts zur Laufzeit an ein anderes Objekt gebunden werden. Kurz gesagt, mit Javascript kann ein Objekt die Methode eines anderen Objekts "ausleihen":
Mit den Methoden
call
undapply
Methoden von Funktionsobjekten (in JavaScript sind Funktionen auch Objekte) können Sie dies tun. In Ihrem Code könnte man also sagen, dass die NodeList die Slice-Methode eines Arrays ausleiht..slice()
Gibt als Ergebnis ein anderes Array zurück, das zum "konvertierten" Array wird, das Sie dann verwenden können.quelle
call
Funktion vonArray.prototype
aka sich[].prototype
selbst anwenden .Es ruft die
slice
Funktion von einem abArray
. Diese Funktion wird dann aufgerufen, wobei jedoch das Ergebnis vondocument.querySelectorAll
alsthis
Objekt anstelle eines tatsächlichen Arrays verwendet wird.quelle
Es ist eine Technik, um Array-ähnliche Objekte in echte Arrays umzuwandeln.
Einige dieser Objekte umfassen:
arguments
in FunktionenDies dient vielen Zwecken, zum Beispiel werden Objekte als Referenz übergeben, während Arrays als Wert übergeben werden.
Beachten Sie auch, dass das erste Argument
0
weggelassen werden kann, eine ausführliche Erklärung hier .Der Vollständigkeit halber gibt es auch jQuery.makeArray () .
quelle
Dies ist der Code, den wir haben,
Lass es uns zuerst zerlegen,
Schritt: 1 Ausführung der
call
Funktioncall
werdenthisArg
die restlichen Argumente an eine Argumentliste angehängt.slice
aufgerufen, indem ihrthis
Wert alsthisArg
(Array-ähnliches Objekt stammt vondocument.querySelector
) und mit der Argumentliste gebunden werden . dh] Argument,start
das enthält0
Schritt: 2 Ausführung der
slice
innerhalb von aufgerufenen Funktioncall
start
wird einer Variablens
als zugewiesen0
end
istundefined
,this.length
wird in gespeicherte
a
Nachdem Sie die obigen Einstellungen vorgenommen haben, wird die folgende Iteration durchgeführt
a
wird als Ergebnis zurückgegeben.PS Zum besseren Verständnis unseres Szenarios wurden einige Schritte, die für unseren Kontext erforderlich sind, vom ursprünglichen Algorithmus für Aufruf und Slice ignoriert .
quelle
quelle
Von ES6: Erstellen Sie einfach ein Array mit Array.from (element.children) oder Array.from ({length: 5}).
quelle