Javascript-Effizienz: 'for' vs 'forEach' [geschlossen]

103

Was ist der aktuelle Standard in 2017 in Javascript mit for () Schleifen vs .forEach.

Zur Zeit arbeite ich mich durch Colt Steeles „Web Dev Boot Camp“ auf Udemy und er spricht forEachüber forseine Lehre. Ich habe jedoch während der Übungen im Rahmen der forKursarbeit nach verschiedenen Dingen gesucht und finde immer mehr Empfehlungen, eine- Schleife anstelle von zu verwenden forEach. Die meisten Leute scheinen zu sagen, dass die for-Schleife effizienter ist.

Ist dies etwas, das sich seit dem Schreiben des Kurses (ca. 2015) geändert hat, oder sind es die wirklichen Vor- und Nachteile für jeden, den man mit mehr Erfahrung lernen wird?

Jeder Rat wäre sehr dankbar.

Tonyrobbins
quelle
11
Warum binden Sie sich an die subjektive Vorstellung eines 2017er Standards? Nehmen Sie einen zeitlosen Standard an, wie das Schreiben von sauberem, wartbarem Code, in dem Wissen, dass Ingenieure hart daran arbeiten, die am häufigsten verwendeten Konstrukte sehr effizient zu machen, und optimieren Sie dann die Leistung, wenn Sie ein bestimmtes Leistungsproblem haben
2
Ein Eingeborener forist für reine Geschwindigkeit schwer zu schlagen. forEach()ruft für jede Iteration einen Rückruf auf; Das bringt natürlich etwas Aufwand mit sich.
Kanon
1
Als Entwickler, den ich kaum für oder für jeden benutze, wird der größte Teil der Arbeit durch Zuordnen, Filtern oder Reduzieren von Methoden erledigt.
AT
12
@AT, solange Sie nicht zu den Leuten gehören, die mapnur für die Iteration verwenden und das neue Array, das es generiert, verwerfen . Ich weiß nicht, wie viele Personen ich allein auf dieser Site für diese bestimmte Funktionsauswahl korrigieren musste.
Kanon
1
@canon stimmte zu, die Auswahl der Schleife ist wichtig und man sollte die Ausgabe und den Rückstand solcher Methoden bei der Auswahl berücksichtigen. Ich glaube, aus Gründen der Lesbarkeit sollte einfach "for loops" vermieden werden.
AT

Antworten:

196

zum

forSchleifen sind viel effizienter. Es ist ein Schleifenkonstrukt spezifisch zu iterieren ausgelegt , während eine Bedingung ist wahr , die gleichzeitig einen Schrittmechanismus bietet ( im Allgemeinen den Iterator zu erhöhen). Beispiel:

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

Dies soll nicht bedeuten , dass for- Schleifen immer effizienter sind, nur dass JS-Engines und Browser sie so optimiert haben. Im Laufe der Jahre gab es Kompromisse, welches Schleifenkonstrukt effizienter ist (z. B. für, während, reduzieren, umkehren usw.) - verschiedene Browser und JS-Engines haben ihre eigenen Implementierungen, die unterschiedliche Methoden bieten, um dieselben Ergebnisse zu erzielen. Wenn Browser weiter optimiert werden, um die Leistungsanforderungen zu erfüllen, [].forEachkönnten sie theoretisch so implementiert werden, dass sie schneller oder vergleichbar mit a sind for.

Leistungen:

  • effizient
  • vorzeitige Beendigung der Schleife (Ehrungen breakund continue)
  • Bedingungskontrolle ( i<nkann alles sein und ist nicht an die Größe eines Arrays gebunden)
  • variabler Umfang ( var iBlätter iverfügbar, nachdem die Schleife endet)

für jedes

.forEachsind Methoden, die hauptsächlich über Arrays iterieren (auch über andere Aufzählungen wie z. B. Mapund SetObjekte). Sie sind neuer und bieten Code, der subjektiv leichter zu lesen ist. Beispiel:

[].forEach((val, index)=>{
   ...
});

Leistungen:

  • beinhaltet keine Variableneinrichtung (iteriert über jedes Element des Arrays)
  • Funktionen / Pfeilfunktionen erweitern die Variable auf den Block
    Im obigen Beispiel valwäre dies ein Parameter der neu erstellten Funktion. Daher würden alle Variablen, die valvor der Schleife aufgerufen werden , ihre Werte nach deren Ende beibehalten.
  • subjektiv wartbarer, da es möglicherweise einfacher ist zu identifizieren, was der Code tut - er iteriert über eine Aufzählung; Eine for-Schleife könnte für eine beliebige Anzahl von Schleifenschemata verwendet werden

Performance

Leistung ist ein heikles Thema, das im Allgemeinen einige Erfahrung erfordert, wenn es um Voraussicht oder Herangehensweise geht. Um im Voraus (während der Entwicklung) zu bestimmen, wie viel Optimierung erforderlich sein kann, muss ein Programmierer eine gute Vorstellung von den Erfahrungen mit dem Problemfall in der Vergangenheit sowie ein gutes Verständnis für mögliche Lösungen haben.

In einigen Fällen kann die Verwendung von jQuery zu langsam sein (ein erfahrener Entwickler weiß das möglicherweise), während andere Zeiten kein Problem darstellen. In diesem Fall ist die browserübergreifende Konformität der Bibliothek und die einfache Ausführung anderer Funktionen (z. B. AJAX, Event-Handling) wäre die eingesparte Entwicklungs- (und Wartungs-) Zeit wert.

Ein anderes Beispiel ist, wenn Leistung und Optimierung alles wären, gäbe es keinen anderen Code als Maschine oder Baugruppe. Offensichtlich ist dies nicht der Fall, da es viele verschiedene Hoch- und Niedrigsprachen gibt, von denen jede ihre eigenen Kompromisse hat. Diese Kompromisse umfassen, ohne darauf beschränkt zu sein, Spezialisierung, einfache und schnelle Entwicklung, einfache und schnelle Wartung, optimierten Code, fehlerfreien Code usw.

Ansatz

Wenn Sie nicht genau wissen, ob für etwas optimierter Code erforderlich ist, ist es im Allgemeinen eine gute Faustregel, zuerst wartbaren Code zu schreiben. Von dort aus können Sie testen und genau bestimmen, was bei Bedarf mehr Aufmerksamkeit erfordert.

Bestimmte offensichtliche Optimierungen sollten jedoch Teil der allgemeinen Praxis sein und keinen Gedanken erfordern. Betrachten Sie beispielsweise die folgende Schleife:

for (var i=0; i < arr.length; ++i ){}

Für jede Iteration der Schleife ruft JavaScript die Kostenvorgänge für die arr.lengthSchlüsselsuche in jedem Zyklus ab. Es gibt keinen Grund, warum dies nicht sein sollte:

for (var i=0, n=arr.length; i < n; ++i){}

Dies macht dasselbe, ruft jedoch nur arr.lengtheinmal ab, speichert die Variable zwischen und optimiert Ihren Code.

vol7ron
quelle
22
Hervorragende, gründliche, nicht anmaßende Antwort, die nicht an einen einzelnen Zeitpunkt, eine Implementierung oder einen Mikro-Benchmark-Test gebunden ist.
1
Perfekt, genau das habe ich gesucht und es gibt viel mehr Tiefe als das Video könnte. Ich weiß das wirklich zu schätzen, da es so viel zu lernen gibt, und es sind die Dinge, die man leicht überspringen kann, wenn man sich ohne Grund gegenseitig bevorzugt, was Sie in Zukunft behindern könnte. Danke vielmals!
Tonyrobbins
2
for-loop hat oft einen Vorteil in Bezug auf das Debuggen: Sie sind zivilisiert, um einzusteigen, zu brechen und zu inspizieren. Mit forEach () kann die zusätzliche Rückrufstufe die Sache etwas komplizieren.
Eric Grange
1
@FelipeBuccioni Danke, ich wollte das eigentlich untersuchen, da ich denke, dass die Engines jetzt prüfen, ob ein Array mutiert ist, um festzustellen, ob die Länge zwischengespeichert ist. Aus Legacy-Gründen waren die Optimierungs-Engines meiner Meinung nach nicht so großzügig und die Länge war bei jeder Iteration ein Leistungseinbruch. Ich werde einen Blick auf Ihren Artikel werfen und das in die Antwort aufnehmen, wenn ich Zeit habe, oder hoffentlich wird ein herausragendes Mitglied der Community eine Änderung als Bearbeitung für mich
vornehmen
6
Ich mag die Erklärung in dieser Antwort und den Satz sehr [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Ich glaube, dass mit der letAnweisung zum Deklarieren einer lokalen Variablen für den Blockbereich der zweite Vorteil von forEachkein Vorteil mehr gegenüber der forSchleife ist, es sei denn in einer Umgebung ohne Unterstützung für let.
user7393973