2083 Stimmen

Warum ist es keine gute Idee, "for...in" für die Iteration von Arrays zu verwenden?

Ich wurde darauf hingewiesen, dass ich in JavaScript for...in nicht mit Arrays verwenden soll. Warum?

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?

46voto

WynandB Punkte 1317

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...

  • Die Verwendung von 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.
  • Die Verwendung von 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.

41voto

JacquesB Punkte 40790

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.

``

35voto

ctmiddle Punkte 351

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.

`

6 Stimmen

Du kannst das Präfix + anstelle von parseInt verwenden, es sei denn, du benötigst wirklich eine Ganzzahl oder ignorierst ungültige Zeichen.

0 Stimmen

Auch die Verwendung von parseInt() wird nicht empfohlen. Versuche parseInt("025"); und es wird fehlschlagen.

7 Stimmen

@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.

23voto

cHao Punkte 81921

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.

19voto

Lior Punkte 1571

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.

2 Stimmen

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.

2 Stimmen

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.

0 Stimmen

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.com

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.

Powered by:

X