[]
ist ein Array.
Dieses Array wird überhaupt nicht verwendet.
Es wird auf die Seite gestellt, da Sie durch die Verwendung eines Arrays Zugriff auf Array-Prototypen wie z .forEach
.
Dies ist nur schneller als das Tippen Array.prototype.forEach.call(...);
Als nächstes forEach
ist eine Funktion, die eine Funktion als Eingabe nimmt ...
[1,2,3].forEach(function (num) { console.log(num); });
... und für jedes Element in this
(wo this
es Array-ähnlich ist, indem es ein hat length
und Sie auf seine Teile wie zugreifen können this[1]
) werden drei Dinge übergeben:
- das Element im Array
- der Index des Elements (drittes Element würde passieren
2
)
- ein Verweis auf das Array
Schließlich .call
ist ein Prototyp, den Funktionen haben (es ist eine Funktion, die für andere Funktionen aufgerufen wird).
.call
nimmt das erste Argument und ersetzt es this
innerhalb der regulären Funktion durch das, was Sie call
als erstes Argument übergeben haben ( undefined
oder null
wird window
im alltäglichen JS verwendet oder ist das, was Sie übergeben haben, wenn es sich im "strengen Modus" befindet). Die restlichen Argumente werden an die ursprüngliche Funktion übergeben.
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ": " + item);
});
// 0: "a"
// 1: "b"
// 2: "c"
Daher erstellen Sie eine schnelle Möglichkeit, die forEach
Funktion aufzurufen , und wechseln this
vom leeren Array zu einer Liste aller <a>
Tags. Für jede <a>
Reihenfolge rufen Sie die bereitgestellte Funktion auf.
BEARBEITEN
Logische Schlussfolgerung / Bereinigung
Unten finden Sie einen Link zu einem Artikel, der darauf hinweist, dass wir Versuche der funktionalen Programmierung abschaffen und uns jedes Mal an manuelle Inline-Schleifen halten, da diese Lösung hackig und unansehnlich ist.
Ich würde sagen , dass , während .forEach
weniger hilfreich als seine Kollegen, .map(transformer)
, .filter(predicate)
, .reduce(combiner, initialValue)
, es dient immer noch Zwecke , wenn alles , was Sie wirklich wollen , ist die Außenwelt ändern (nicht das Array), n-mal, während Zugang zu entweder arr[i]
oder i
.
Wie gehen wir mit der Ungleichheit um, da Motto eindeutig ein talentierter und sachkundiger Typ ist und ich mir vorstellen möchte, dass ich weiß, was ich tue / wohin ich gehe (ab und zu ... ... andere) Mal ist es Head-First-Lernen)?
Die Antwort ist eigentlich recht einfach, und Onkel Bob und Sir Crockford würden aufgrund des Versehens beide Gesichtspalmen:
räum es auf .
function toArray (arrLike) { // or asArray(), or array(), or *whatever*
return [].slice.call(arrLike);
}
var checked = toArray(checkboxes).filter(isChecked);
checked.forEach(listValues);
Wenn Sie sich jetzt fragen, ob Sie dies selbst
tun müssen, lautet die Antwort möglicherweise nein ... Genau das erledigt heutzutage ... ... jede (?) Bibliothek mit Funktionen höherer Ordnung.
Wenn Sie lodash oder Unterstrich oder sogar jQuery verwenden, haben alle die Möglichkeit, eine Reihe von Elementen zu übernehmen und eine Aktion n-mal auszuführen.
Wenn Sie so etwas nicht verwenden, schreiben Sie auf jeden Fall Ihre eigenen.
lib.array = (arrLike, start, end) => [].slice.call(arrLike, start, end);
lib.extend = function (subject) {
var others = lib.array(arguments, 1);
return others.reduce(appendKeys, subject);
};
Update für ES6 (ES2015) und darüber hinaus
Eine slice( )
/ array( )
/ etc-Hilfsmethode wird nicht nur Menschen das Leben erleichtern, die Listen genauso verwenden möchten, wie sie Arrays verwenden (wie sie sollten), sondern auch Menschen, die den Luxus haben, in ES6 + -Browsern der relativ nahen Umgebung zu arbeiten Zukunft oder von "Transpilieren" in Babel heute haben Sie Sprachfunktionen eingebaut, die diese Art von Dingen unnötig machen.
function countArgs (...allArgs) {
return allArgs.length;
}
function logArgs (...allArgs) {
return allArgs.forEach(arg => console.log(arg));
}
function extend (subject, ...others) { /* return ... */ }
var nodeArray = [ ...nodeList1, ...nodeList2 ];
Super sauber und sehr nützlich.
Suchen Sie nach den Operatoren Rest und Spread . Probieren Sie sie auf der BabelJS-Website aus. Wenn Ihr Tech-Stack in Ordnung ist, verwenden Sie ihn in der Produktion mit Babel und einem Build-Schritt.
Es gibt keinen guten Grund , nicht in der Lage sein , die aus Nicht-Array in einem Array umwandeln zu verwenden ... ... macht nicht nur ein Durcheinander von Code nichts zu tun , aber der gleichen hässlicher Linie einfügen, überall.
.call
nicht ändern den Wertthis
, weshalb Sie verwendencall
mit dem forEach. Wenn forEach so aussieht , bedeutet dasforEach (fn) { var i = 0; var len = this.length; for (; i < length; i += 1) { fn( this[i], i, this ); }
Ändernthis
durch SagenforEach.call( newArrLike )
, dass das neue Objekt als verwendet wirdthis
..call
nicht den Wert der Änderungthis
innerhalb dessen , was Sie passieren zuforEach
,.call
ändert sich der Wert vonthis
innen forEach . Wenn Sie sich als zu verwechseln sind , warumthis
nicht weitergegeben BekommtforEach
in die Funktion , die Sie genannt wollten, dann sollten Sie das Verhalten nachschlagenthis
in JavaScript. Als Zusatz, anwendbar nur hier (und Karte / Filter / verringern), ist ein zweites ArgumentforEach
, die Sätzethis
in der Funktionarr.forEach(fn, thisInFn)
oder[].forEach.call(arrLike, fn, thisInFn);
oder Verwendung.bind
;arr.forEach(fn.bind(thisInFn));
[]
ist nur als Array vorhanden, damit Sie.call
die.forEach
Methode verwenden und diethis
zu dem Satz ändern können, an dem Sie arbeiten möchten..call
sieht wie folgt aus :function (thisArg, a, b, c) { var method = this; method(a, b, c); }
außer , dass es interne schwarz-Magie - Setthis
innerhalb dermethod
gleich , was Sie übergeben , wiethisArg
.Die
querySelectorAll
Methode gibt ein zurückNodeList
, das einem Array ähnelt, aber kein Array ist. Daher gibt es keineforEach
Methode (über die Array-Objekte erbenArray.prototype
).Da a
NodeList
einem Array ähnlich ist, funktionieren Array-Methoden tatsächlich damit. Wenn Sie also verwenden[].forEach.call
, rufen Sie dieArray.prototype.forEach
Methode im Kontext von aufNodeList
, als ob Sie dies einfach hätten tun könnenyourNodeList.forEach(/*...*/)
.Beachten Sie, dass das leere Array-Literal nur eine Verknüpfung zur erweiterten Version ist, die Sie wahrscheinlich auch häufig sehen werden:
quelle
[].forEach.call(['a','b'], cb)
Over['a','b'].forEach(cb)
in alltäglichen Anwendungen mit Standard-Arrays, nur wenn versucht wird, über Array-ähnliche Strukturen zu iterieren, die keinenforEach
eigenen Prototyp haben? Ist das korrekt?[].forEach()
:)var section = document.querySelectorAll(".section"); section.forEach((item)=>{ console.log(item.offsetTop) })
funktioniert gutforEach
Arrays unterstützen, aber keine NodeList-Objekte)Die anderen Antworten haben diesen Code sehr gut erklärt, daher füge ich nur einen Vorschlag hinzu.
Dies ist ein gutes Beispiel für Code, der der Einfachheit und Klarheit halber überarbeitet werden sollte. Anstatt
[].forEach.call()
oderArray.prototype.forEach.call()
jedes Mal, wenn Sie dies tun, eine einfache Funktion daraus zu machen:Jetzt können Sie diese Funktion anstelle des komplizierteren und undurchsichtigeren Codes aufrufen:
quelle
Es kann besser mit geschrieben werden
Es wird
document.querySelectorAll('a')
ein Objekt zurückgegeben, das einem Array ähnlich ist, aber nicht vomArray
Typ erbt . Wir rufen also dieforEach
Methode aus demArray.prototype
Objekt mit dem Kontext als dem von zurückgegebenen Wert aufdocument.querySelectorAll('a')
quelle
Es ist im Grunde das gleiche wie:
quelle
Möchten Sie diese alte Frage aktualisieren:
Der Grund für
[].foreach.call()
das Durchlaufen von Elementen in modernen Browsern ist größtenteils vorbei. Wir könnendocument.querySelectorAll("a").foreach()
direkt verwenden.quelle
Ein leeres Array hat
forEach
in seinem Prototyp eine Eigenschaft, die ein Funktionsobjekt ist. (Das leere Array ist nur eine einfache Möglichkeit, einen Verweis auf dieforEach
Funktion allerArray
Objekte zu erhalten.) Funktionsobjekte haben wiederum einecall
Eigenschaft, die auch eine Funktion ist. Wenn Sie die Funktion einer Funktion aufrufencall
, wird die Funktion mit den angegebenen Argumenten ausgeführt. Das erste Argument wirdthis
in der aufgerufenen Funktion.Dokumentation zur
call
Funktion finden Sie hier . Dokumentation fürforEach
ist hier .quelle
Fügen Sie einfach eine Zeile hinzu:
Und voila!
Genießen :-)
Warnung: NodeList ist eine globale Klasse. Verwenden Sie diese Empfehlung nicht, wenn Sie eine öffentliche Bibliothek schreiben. Es ist jedoch eine sehr bequeme Möglichkeit, die Selbstwirksamkeit zu steigern, wenn Sie an einer Website oder einer node.js-App arbeiten.
quelle
Nur eine schnelle und schmutzige Lösung, die ich am Ende immer benutze. Ich würde Prototypen nicht anfassen, genauso gute Praxis. Natürlich gibt es viele Möglichkeiten, dies zu verbessern, aber Sie haben die Idee.
quelle
[]
Gibt immer ein neues Array zurück. Dies entspricht einem Array, es wirdnew Array()
jedoch garantiert zurückgegeben, daArray
es vom Benutzer überschrieben werden[]
kann, während dies nicht möglich ist. Dies ist also ein sicherer Weg, um den Prototyp zu erhaltenArray
, der dann wie beschriebencall
verwendet wird, um die Funktion auf der arraylike Knotenliste (this) auszuführen.quelle
[]
wird in der Tat immer ein Array zurückgeben, währendwindow.Array
kann mit irgendetwas überschrieben werden (in allen alten Browsern), kannwindow.Array.prototype.forEach
auch mit irgendetwas überschrieben werden. In beiden Fällen gibt es keine Garantie für die Sicherheit in Browsern, die keine Getter / Setter oder Versiegelung / Einfrieren von Objekten unterstützen (Einfrieren verursacht eigene Erweiterungsprobleme).prototype
oder ihrer Methoden hinzuzufügen :forEach
.Norguard erklärte, WAS
[].forEach.call()
und James Allardice WARUM wir es tun: weil querySelectorAll eine zurückgibtNodeList
, die keine forEach-Methode hat ...Es sei denn, Sie haben einen modernen Browser wie Chrome 51+, Firefox 50+, Opera 38, Safari 10.
Wenn nicht, können Sie eine Polyfüllung hinzufügen :
quelle
Viele gute Informationen auf dieser Seite (siehe Antwort + Antwort + Kommentar ), aber ich hatte kürzlich die gleiche Frage wie das OP, und es dauerte einige Grabungen, um das ganze Bild zu erhalten. Hier ist eine kurze Version:
Das Ziel ist es,
Array
Methoden auf einem Array zu verwendenNodeList
, das diese Methoden selbst nicht hat.Ein älteres Muster hat die Methoden von Array über kooptiert
Function.call()
und ein Array-Literal ([]
) verwendet, anstattArray.prototype
dass es kürzer zu tippen war:Ein neueres Muster (nach ECMAScript 2015) ist zu verwenden
Array.from()
:quelle