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?

17voto

John Slegers Punkte 41127

Ich glaube nicht, dass ich viel zu z. B. Triptychs Antwort oder CMS' Antwort darüber, warum die Verwendung von for...in in einigen Fällen vermieden werden sollte, hinzuzufügen habe.

Ich möchte jedoch hinzufügen, dass es in modernen Browsern eine Alternative zu for...in gibt, die in jenen Fällen verwendet werden kann, in denen for...in nicht verwendet werden kann. Diese Alternative ist for...of :

for (var item of items) {
    console.log(item);
}

Hinweis :

Leider unterstützt keine Version des Internet Explorer for...of (Edge 12+ schon), sodass Sie noch ein wenig warten müssen, bis Sie es in Ihrem Client-Produktionscode verwenden können. Es sollte jedoch sicher sein, es in Ihrem Server-Seiten-JS-Code zu verwenden (wenn Sie Node.js verwenden).

16voto

vava Punkte 23765

Weil es die Objektfelder nummeriert durchgeht, nicht durch Indizes. Sie können den Wert mit dem Index "Länge" abrufen und ich bezweifle, dass Sie dies möchten.

3 Stimmen

Im Firefox 3 könnten Sie entweder arr.forEach oder for(var [i, v] in Iterator(arr)) {} verwenden, aber keiner von beiden funktioniert in IE, obwohl Sie die forEach-Methode selbst schreiben können.

5 Stimmen

Diese Antwort ist falsch. "Länge" wird nicht in der for-in-Iteration enthalten sein. Es werden nur Eigenschaften enthalten, die Sie selbst hinzufügen.

15voto

Pointy Punkte 387467

Das Problem mit for ... in ... — und das wird nur zu einem Problem, wenn ein Programmierer die Sprache nicht wirklich versteht; es ist nicht wirklich ein Fehler oder so — ist, dass es über alle Mitglieder eines Objekts iteriert (nun ja, alle aufzählbaren Mitglieder, aber das ist jetzt ein Detail). Wenn Sie also nur über die indexierten Eigenschaften eines Arrays iterieren möchten, ist der einzige garantierte Weg, um die semantische Konsistenz zu gewährleisten, die Verwendung eines ganzzahligen Index (das heißt, eine Schleife im Stil von for (var i = 0; i < array.length; ++i)).

Jedes Objekt kann beliebige Eigenschaften haben. Es wäre nichts Schreckliches, zusätzliche Eigenschaften zu einer Array-Instanz zu laden. Code, der nur indexierte array-ähnliche Eigenschaften sehen möchte, muss also bei einem ganzzahligen Index bleiben. Code, der sich vollständig dessen bewusst ist, was for ... in tut und wirklich alle Eigenschaften sehen muss, nun, das ist auch in Ordnung.

0 Stimmen

Schöne Erklärung, Pointy. Nur aus Neugier. Wenn ich ein Array habe, das sich in einem Objekt mit mehreren Eigenschaften befindet, und ich for in verwende, im Vergleich zu einer normalen for-Schleife, würden diese Arrays dann durchlaufen werden? (was im Grunde genommen die Leistung verlangsamen würde, oder?)

2 Stimmen

@NiCkNewman Nun, das Objekt, auf das Sie sich nach in in einer for ... in Schleife beziehen, wird einfach

0 Stimmen

Ich verstehe. Ich frage nur, weil ich Objekte und Arrays innerhalb meines Hauptspielobjekts habe und mich frage, ob es schmerzhafter wäre, dafür zu sorgen, als einfach eine normale for-Schleife über die Indizes zu verwenden.

12voto

Redu Punkte 22159

TL & DR: Die Verwendung der for in-Schleife in Arrays ist nicht böse, im Gegenteil.

Ich denke, die for in-Schleife ist ein Juwel von JS, wenn sie in Arrays korrekt verwendet wird. Sie sollten die volle Kontrolle über Ihre Software haben und wissen, was Sie tun. Lassen Sie uns die genannten Nachteile ansehen und diese nach und nach widerlegen.

  1. Es durchläuft auch geerbte Eigenschaften: Zunächst sollten alle Erweiterungen des Array.prototype mit Object.defineProperty() vorgenommen und ihr enumerable-Descriptor auf false gesetzt worden sein. Jede Bibliothek, die dies nicht tut, sollte überhaupt nicht verwendet werden.
  2. Eigenschaften, die Sie später in die Vererbungskette hinzufügen, werden mitgezählt: Beim Unterklassen von Arrays mit Object.setPrototypeOf oder durch die Klassen-erweiterung. Sie sollten erneut Object.defineProperty() verwenden, das standardmäßig die writable, enumerable und configurable-Eigenschafts-Descriptor auf false setzt. Werfen wir hier einen Blick auf ein Beispiel für das Unterklassen von Arrays...

    function Stack(...a){ var stack = new Array(...a); Object.setPrototypeOf(stack, Stack.prototype); return stack; } Stack.prototype = Object.create(Array.prototype); // now stack has full access to array methods. Object.defineProperty(Stack.prototype,"constructor",{value:Stack}); // now Stack is a proper constructor Object.defineProperty(Stack.prototype,"peak",{value: function(){ // add Stack "only" methods to the Stack.prototype. return this[this.length-1]; } }); var s = new Stack(1,2,3,4,1); console.log(s.peak()); s[s.length] = 7; console.log("length:",s.length); s.push(42); console.log(JSON.stringify(s)); console.log("length:",s.length);

    for(var i in s) console.log(s[i]);

Also sehen Sie.. die for in-Schleife ist jetzt sicher, da Sie sich um Ihren Code gekümmert haben.

  1. Die for in-Schleife ist langsam: Auf keinen Fall. Es ist bei weitem die schnellste Methode der Iteration, wenn Sie über schwach besetzte Arrays iterieren, die von Zeit zu Zeit benötigt werden. Dies ist einer der wichtigsten Leistungstricks, die man kennen sollte. Sehen wir uns ein Beispiel an. Wir werden über ein schwach besetztes Array iterieren.

    var a = []; a[0] = "zero"; a[10000000] = "zehn Millionen"; console.time("for-Schleife über Array a:"); for(var i=0; i < a.length; i++) a[i] && console.log(a[i]); console.timeEnd("for loop on array a:"); console.time("for in-Schleife über Array a:"); for(var i in a) a[i] && console.log(a[i]); console.timeEnd("for in loop on array a:");

10voto

Willem van der Veen Punkte 26043

Hier sind die Gründe, warum dies (normalerweise) eine schlechte Praxis ist:

  1. for...in-Schleifen iterieren über alle ihre eigenen aufzählbaren Eigenschaften und die aufzählbaren Eigenschaften ihrer Prototypen. Normalerweise wollen wir bei einer Array-Iteration nur über das Array selbst iterieren. Und auch wenn Sie selbst nichts zum Array hinzufügen, könnten Ihre Bibliotheken oder Frameworks etwas hinzufügen.

Beispiel:

Array.prototype.hithere = 'hithere';

var array = [1, 2, 3];
for (let el in array){
    // die hithere-Eigenschaft wird auch durchlaufen
    console.log(el);
}
  1. for...in-Schleifen garantieren keine spezifische Iterationsreihenfolge. Obwohl die Reihenfolge heutzutage in den meisten modernen Browsern üblich ist, gibt es immer noch keine 100%ige Garantie.
  2. for...in-Schleifen ignorieren undefined Array-Elemente, d.h. Array-Elemente, denen noch kein Wert zugewiesen wurde.

Beispiel::

const arr = []; 
arr[3] = 'foo';   // Array auf 4 vergrößern
arr[4] = undefined; // Ein weiteres Element mit dem Wert undefined hinzufügen

// Über das Array iterieren, eine for-Schleife zeigt die undefinierten Elemente an
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

console.log('\n');

// for in ignoriert die undefinierten Elemente
for (let el in arr) {
    console.log(arr[el]);
}

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