Ich habe die folgende Schleifenanmerkung in einem großen Projekt gefunden, an dem ich arbeite (Pseudocode):
var someOtherArray = [];
for (var i = 0, n = array.length; i < n; i++) {
someOtherArray[i] = modifyObjetFromArray(array[i]);
}
Was meine Aufmerksamkeit auf sich gezogen hat, ist diese zusätzliche "n" -Variable. Ich habe noch nie einen so geschriebenen for lop gesehen.
Offensichtlich gibt es in diesem Szenario keinen Grund, warum dieser Code nicht folgendermaßen geschrieben werden konnte (was ich sehr gewohnt bin):
var someOtherArray = [];
for (var i = 0; i < array.length; i++) {
someOtherArray[i] = modifyObjetFromArray(array[i]);
}
Aber es hat mich zum Nachdenken gebracht.
Gibt es ein Szenario, in dem das Schreiben einer solchen for-Schleife sinnvoll wäre? Die Idee kommt in den Sinn, dass sich die "Array" -Länge während der Ausführung der for-Schleife ändern kann, aber wir möchten nicht weiter als bis zur ursprünglichen Größe schleifen, aber ich kann mir ein solches Szenario nicht vorstellen.
Das Verkleinern des Arrays innerhalb der Schleife ist ebenfalls nicht sehr sinnvoll, da wir wahrscheinlich OutOfBoundsException erhalten.
Gibt es ein bekanntes Entwurfsmuster, bei dem diese Anmerkung nützlich ist?
Bearbeiten Wie von @ Jerry101 angegeben, ist der Grund die Leistung. Hier ist ein Link zu dem von mir erstellten Leistungstest: http://jsperf.com/ninforloop . Meiner Meinung nach ist der Unterschied nicht groß genug, es sei denn, Sie iterieren durch ein sehr großes Array. Der Code, von dem ich ihn kopiert habe, hatte nur bis zu 20 Elemente, daher überwiegt meiner Meinung nach die Lesbarkeit in diesem Fall die Leistungsaspekte.
quelle
n
möglicherweise langsamer als die verwendete Variante,array.Length
da der JITter möglicherweise nicht bemerkt, dass er die Überprüfung der Array-Grenzen eliminieren kann.Antworten:
Die Variable
n
stellt sicher, dass der generierte Code nicht bei jeder Iteration die Array-Länge abruft.Es handelt sich um eine Optimierung, die je nach verwendeter Sprache einen Unterschied in der Laufzeit bewirken kann, unabhängig davon, ob das Array tatsächlich ein Sammlungsobjekt oder ein JavaScript- "Array" ist, sowie andere Optimierungsdetails.
quelle
n
auf die Schleife, was normalerweise eine gute Sache ist. Ich würde es nur vor der Schleife definieren, wenn ich es später wieder verwenden wollte.Das Abrufen der Länge des Arrays kann leicht "teurer" sein als die tatsächliche Aktion, über die Sie iterieren.
Wenn sich die Menge nicht ändert, fragen Sie die Länge nur einmal ab.
Nicht mit Arrays, sondern mit Datensatzgruppen, die von einem SQL-Server stammen. Ich habe dramatische Verbesserungen festgestellt, indem ich nicht bei jeder Iteration die Anzahl der Datensätze abgefragt habe. (Tun Sie dies natürlich nur, wenn Sie garantieren können, dass Ihr Array oder Datensatz während dieses Vorgangs nicht geändert wird).
quelle
Die Leute, die über Leistung sprechen, haben wahrscheinlich Recht, dass dies der Grund ist, warum es so geschrieben wurde (die Person, die es so geschrieben hat, ist möglicherweise nicht richtig, dass es die Leistung erheblich beeinflusst, aber das ist eine andere Sache).
Um diesen Teil Ihrer Frage zu beantworten, ist es meiner Meinung nach am wahrscheinlichsten, wenn der Hauptzweck der Schleife darin besteht, das Array zu ändern, über das sie eine Schleife durchläuft. Betrachten Sie so etwas im Pseudocode:
Natürlich gibt es auch andere Möglichkeiten, es zu schreiben. In diesem Fall hätte ich gleichzeitig mit der Überprüfung, ob die Empfänger ihre Einladungen angenommen haben, nach Plus suchen und die vollständige Gästeliste nacheinander erstellen können. Ich möchte diese beiden Operationen nicht unbedingt kombinieren, aber ich kann mir nicht sofort einen Grund vorstellen, warum das definitiv falsch ist, und daher ist dieses Design erforderlich . Es ist eine Option, die gelegentlich in Betracht gezogen werden sollte.
Eigentlich denke ich, dass das, was an diesem Code am meisten falsch ist, ist, dass die Mitgliedschaft im
guests
Array an verschiedenen Stellen im Code verschiedene Dinge bedeutet. Daher würde ich es sicherlich nicht als "Muster" bezeichnen, aber ich weiß nicht, dass es ein ausreichender Defekt ist, um auszuschließen, jemals etwas in dieser Art zu tun :-)quelle
Wenn möglich, sollten Sie einen Iterator verwenden, der alle Elemente des Arrays durchläuft. Sie verwenden das Array nur als Sequenz und nicht als Speicher mit wahlfreiem Zugriff. Es ist daher offensichtlich, dass ein Iterator, der nur einen sequentiellen Zugriff ausführt, schneller ist. Stellen Sie sich vor, was Sie denken, dass ein Array tatsächlich ein Binärbaum ist, aber jemand hat Code geschrieben, der die "Länge" durch Zählen der Elemente bestimmt, und Code, der auf das i-te Element zugreift, auch durch Durchlaufen des Elements, jeweils in O (n) ). Ein Iterator kann sehr schnell sein, Ihre Schleife wird langsam sein.
quelle