Ich wurde darauf hingewiesen, dass ich in JavaScript for...in
nicht mit Arrays verwenden soll. Warum?
Du kannst das Präfix +
anstelle von parseInt
verwenden, es sei denn, du benötigst wirklich eine Ganzzahl oder ignorierst ungültige Zeichen.
Ich wurde darauf hingewiesen, dass ich in JavaScript for...in
nicht mit Arrays verwenden soll. Warum?
Kurze Antwort: Es lohnt sich einfach nicht.
Längere Antwort: Es lohnt sich einfach nicht, auch wenn die Reihenfolge der Elemente und die optimale Leistung nicht erforderlich sind.
Lange Antwort: Es lohnt sich einfach nicht...
for (var property in array)
führt dazu, dass array
als ein Objekt durchlaufen wird, das die Objekt-Prototypenkette durchläuft und letztendlich langsamer als eine indexbasierte for
-Schleife ausgeführt wird.for (... in ...)
garantiert nicht, dass die Objekteigenschaften in sequentieller Reihenfolge zurückgegeben werden, wie man es erwarten würde.hasOwnProperty()
und !isNaN()
Überprüfungen zur Filterung der Objekteigenschaften ist ein zusätzlicher Overhead, der dazu führt, dass es noch langsamer ausgeführt wird und den Hauptgrund für die Verwendung zunichte macht, nämlich wegen des prägnanteren Formats.Aus diesen Gründen existiert kein akzeptabler Kompromiss zwischen Leistung und Bequemlichkeit. Es gibt wirklich keinen Nutzen, es sei denn, die Absicht besteht darin, das Array als Objekt zu behandeln und Operationen auf den Objekteigenschaften des Arrays durchzuführen.
In Isolation ist nichts falsch daran, for-in bei Arrays zu verwenden. For-in iteriert über die Eigenschaftsnamen eines Objekts, und im Falle eines "out-of-the-box" Arrays entsprechen die Eigenschaften den Array-Indizes. (Die eingebauten Eigenschaften wie length
, toString
und so weiter werden nicht in der Iteration enthalten.)
Wenn Ihr Code (oder das von Ihnen verwendete Framework) jedoch benutzerdefinierte Eigenschaften zu Arrays oder zum Array-Prototyp hinzufügt, werden diese Eigenschaften in der Iteration enthalten sein, was wahrscheinlich nicht das ist, was Sie wollen.
Einige JS-Frameworks wie Prototype modifizieren den Array-Prototypen. Andere Frameworks wie JQuery tun dies nicht, daher können Sie mit JQuery sicher for-in verwenden.
Wenn Sie unsicher sind, sollten Sie wahrscheinlich kein for-in verwenden.
Ein alternativer Weg, um durch ein Array zu iterieren, ist die Verwendung einer for-Schleife:
for (var ix=0;ix
``
Das hat jedoch ein anderes Problem. Das Problem ist, dass ein JavaScript-Array "Löcher" haben kann. Wenn Sie arr
wie folgt definieren:
var arr = ["hello"];
arr[100] = "goodbye";
Dann hat das Array zwei Elemente, aber eine Länge von 101. Die Verwendung von for-in liefert also zwei Indizes, während die for-Schleife 101 Indizes liefert, wobei der 99. einen Wert von undefined
hat.
``
Zusätzlich zu den Gründen in anderen Antworten könnten Sie die "for...in"-Struktur nicht verwenden wollen, wenn Sie mit der Zählervariable mathematische Operationen durchführen müssen, da die Schleife durch die Namen der Eigenschaften des Objekts iteriert und die Variable daher eine Zeichenfolge ist.
Zum Beispiel,
for (var i=0; i
`
wird es schreiben
0, number, 1
1, number, 2
...
während
for (var ii in a) {
document.write(i + ', ' + typeof i + ', ' + i+1);
}
schreiben wird
0, string, 01
1, string, 11
...
Natürlich kann dies leicht überwunden werden, indem Sie
ii = parseInt(ii);
in der Schleife einschließen, aber die erste Struktur ist direkter.
`
Du kannst das Präfix +
anstelle von parseInt
verwenden, es sei denn, du benötigst wirklich eine Ganzzahl oder ignorierst ungültige Zeichen.
Auch die Verwendung von parseInt()
wird nicht empfohlen. Versuche parseInt("025");
und es wird fehlschlagen.
@Derek - Sie können definitiv parseInt
verwenden. Das Problem besteht darin, dass ältere Browser versuchen könnten, die Zahl zu interpretieren, wenn Sie die Basis nicht angeben (so wird 025 zu oktal). Dies wurde in ECMAScript 5 behoben, aber es tritt immer noch bei Zahlen auf, die mit "0x" beginnen (sie interpretiert die Zahl als hexadezimal). Um auf der sicheren Seite zu sein, verwenden Sie die Basis, um die Zahl anzugeben, wie zum Beispiel parseInt("025", 10)
- das gibt die Basis 10 an.
Abgesehen davon, dass für
... in
über alle aufzählbaren Eigenschaften iteriert (was nicht dasselbe ist wie "alle Array-Elemente"!), siehe http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf, Abschnitt 12.6.4 (5. Ausgabe) oder 13.7.5.15 (7. Ausgabe):
Die Mechanik und Reihenfolge des Aufzählens der Eigenschaften ... ist nicht festgelegt...
(Hervorhebung durch mich.)
Das bedeutet, dass ein Browser, wenn er wollte, die Eigenschaften in der Reihenfolge durchgehen könnte, in der sie eingefügt wurden. Oder in numerischer Reihenfolge. Oder in lexikalischer Reihenfolge (wo "30" vor "4" kommt! Beachten Sie, dass alle Objektschlüssel - und damit alle Array-Indizes - tatsächlich Zeichenfolgen sind, also ergibt das total Sinn). Er könnte sie nach Bucket durchgehen, wenn er Objekte als Hashtabellen implementiert hätte. Oder nehme all das und füge "rückwärts" hinzu. Ein Browser könnte sogar willkürlich iterieren und ECMA-262-konform sein, solange er jede Eigenschaft genau einmal besucht.
In der Praxis mögen die meisten Browser derzeit gerne in etwa derselben Reihenfolge iterieren. Aber es gibt nichts, was besagt, dass sie das tun müssen. Das ist implementierungsspezifisch und könnte sich jederzeit ändern, wenn eine andere Methode gefunden wurde, die weitaus effizienter ist.
In jedem Fall trägt für
...in
keine Konnotation von Reihenfolge. Wenn Ihnen die Reihenfolge wichtig ist, geben Sie explizit an und verwenden Sie eine reguläre for
-Schleife mit einem Index.
Hauptsächlich zwei Gründe:
Eins
Wie andere bereits gesagt haben, könnte es sein, dass du Schlüssel erhältst, die nicht in deinem Array sind oder von der Prototypen vererbt wurden. Wenn also, sagen wir mal, eine Bibliothek eine Eigenschaft zu den Array- oder Object-Prototypen hinzufügt:
Array.prototype.someProperty = true
wirst du es als Teil jedes Arrays erhalten:
for (var item in [1,2,3]){
console.log(item) // wird 1,2,3 und auch "someProperty" ausgeben
}
Dies kannst du mit der Methode hasOwnProperty lösen:
var ary = [1,2,3];
for (var item in ary){
if (ary.hasOwnProperty(item)){
console.log(item) // wird nur 1,2,3 ausgeben
}
}
dies gilt jedoch für die Iteration über jedes Objekt mit einer for-in Schleife.
Zwei
Normalerweise ist die Reihenfolge der Elemente in einem Array wichtig, aber die for-in Schleife wird nicht unbedingt in der richtigen Reihenfolge durchlaufen. Das liegt daran, dass das Array als Objekt behandelt wird, wie es in JS implementiert ist, und nicht als Array. Dies scheint eine Kleinigkeit zu sein, kann aber wirklich Anwendungen durcheinander bringen und ist schwer zu debuggen.
Object.keys(a).forEach( function(item) { console.log(item) } )
Iteriere über ein Array von eigenen Eigenschaftsschlüsseln, nicht über diejenigen, die vom Prototyp geerbt wurden.
Richtig, aber ähnlich wie bei der for-in-Schleife muss dies nicht unbedingt in der richtigen Indexreihenfolge erfolgen. Außerdem funktioniert es nicht in älteren Browsern, die ES5 nicht unterstützen.
Sie können diesen Browsern array.forEach
beibringen, indem Sie bestimmten Code in Ihre Skripte einfügen. Siehe Polyfill developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
54 Stimmen
Ich habe die kürzlich gestellte Frage gesehen, bei der jemand das zu Ihnen gesagt hat, aber sie meinten nur für Arrays. Es gilt als schlechte Praxis, durch Arrays zu iterieren, aber nicht unbedingt für die Iteration durch Elemente eines Objekts.
22 Stimmen
Viele Antworten mit "for" -Schleifen wie 'for (var i=0; i
3 Stimmen
@MarkSchultheiss Aber das ist eine Rückwärtsschleife. Gibt es eine andere Version der Vorwärtsschleife, die schneller ist?
1 Stimmen
@MattDiPasquale - ja, es ist umgekehrt, jedoch bei einer bekannten Grenze ermöglicht es eine optimale Verarbeitung, insbesondere in älteren Browsern durch Iteration über eine bekannte Menge vs. eine unbekannte Satzlänge durch Festlegung der Grenze zuerst. Es ist die Natur einer interpretierten Sprache.
0 Stimmen
@MarkSchultheiss Guter Kommentar. Man könnte auch die
for
-Schleife schreiben alsfor (var i = hColl.length; i--;) {}
, was ein ähnliches Leistungsprofil wie die umgekehrtewhile
-Schleife haben sollte.5 Stimmen
@Wynand verwenden Sie
var i = hCol1.length; for (i; i; i--) {}
speichern Sie den i-Zähler, da dies einen Unterschied macht und den Test vereinfacht. - Je älter der Browser ist, desto größer ist der Unterschied zwischenfor
undwhile
IMMER den "i" Zähler zwischenspeichern - und natürlich passt negativ nicht immer zur Situation, und das negativeverdeckt
den Code etwas für einige Leute. und beachten Sievar i = 1000; for (i; i; i--) {}
undvar b = 1000 for (b; b--;) {}
wobei i von 1000 bis 1 und b von 999 bis 0 geht. - Je älter der Browser ist, desto mehr tendiert der while dazu, die Leistung zu favorisieren.12 Stimmen
Du kannst auch schlau sein.
for(var i = 0, l = myArray.length; i < l; ++i) ...
ist die schnellste und beste Möglichkeit, um eine Vorwärtsiteration durchzuführen.0 Stimmen
Es ist jetzt 10 Jahre später und ich verspüre den Drang hinzuzufügen: Auch wenn diese Optimierungen den Code leicht schneller machen: Es handelt sich um Mikro-Optimierungen. Wenn Sie Zweifel haben, entscheiden Sie sich für lesbaren Code, nicht für eine hoch optimierte Schleife über ein Array mit 1000 Elementen. Wenn etwas langsam ist, dann ist es normalerweise der Code, der innerhalb der Schleife ausgeführt wird, nicht die Schleifensteuerstruktur.