2083 Stimmen

Warum ist es eine schlechte Idee, "for...in" zur Iteration von Arrays zu verwenden?

Man hat mir gesagt, for...in nicht mit Arrays in JavaScript zu verwenden. Warum nicht?

54 Stimmen

Ich habe die kürzliche Frage gesehen, in der jemand das zu dir gesagt hat, aber sie meinten nur für Arrays. Es wird als schlechte Praxis betrachtet, 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ärtsiteration. Gibt es eine andere Version der Vorwärtsiteration, die schneller ist?

17voto

John Slegers Punkte 41127

Ich denke nicht, dass ich viel zu z. B. Triptychs Antwort oder CMS' Antwort hinzufügen muss, warum die Verwendung von for...in in einigen Fällen vermieden werden sollte.

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 wird for...of von keiner Version des Internet Explorers unterstützt (Edge 12+ tut es), daher müssen Sie noch ein wenig länger warten, bis Sie es in Ihrem Client-seitigen Produktionscode verwenden können. Es sollte jedoch sicher sein, es in Ihrem Server-seitigen JS-Code zu verwenden (wenn Sie Node.js verwenden).

16voto

vava Punkte 23765

Weil es sich durch Objektfelder aufzählt, nicht durch Indizes. Du kannst den Wert mit dem Index "Länge" bekommen und ich bezweifle, dass du das möchtest.

3 Stimmen

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

5 Stimmen

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

15voto

Pointy Punkte 387467

Das Problem mit for ... in ... — und das wird nur dann ein 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 nur über die indizierten Eigenschaften eines Arrays iterieren möchten, dann ist der einzige garantierte Weg, um die semantische Konsistenz zu wahren, die Verwendung eines Ganzzahl-Index (also eine Schleife im Stil von for (var i = 0; i < array.length; ++i)).

Jedes Objekt kann beliebige Eigenschaften haben. Es wäre nicht schlimm, zusätzliche Eigenschaften auf eine Array-Instanz zu laden. Code, der nur indizierte array-ähnliche Eigenschaften sehen möchte, muss daher bei einem Ganzzahl-Index bleiben. Code, der sich vollständig dessen bewusst ist, was for ... in macht und wirklich alle Eigenschaften sehen muss, das ist auch in Ordnung.

0 Stimmen

Schöne Erklärung Pointy. Nur aus Neugier. Wenn ich ein Array hätte, das sich innerhalb eines Objekts unter multiplen Eigenschaften befindet und for in durchführe, im Vergleich zu einer regulären Schleife, würden diese Arrays durchlaufen werden? (was im Wesentlichen die Leistung verlangsamen würde, oder?)

2 Stimmen

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

0 Stimmen

Ich verstehe. Ich war nur neugierig, weil ich Objekte und Arrays innerhalb meines Hauptspielobjekts habe und mich gefragt habe, ob das für das Iterieren schmerzhafter wäre als einfach eine normale for-Schleife über die Indizes.

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 korrekt in Arrays verwendet wird. Man erwartet, dass Sie die volle Kontrolle über Ihre Software haben und wissen, was Sie tun. Lassen Sie uns die genannten Nachteile sehen und einen nach dem anderen widerlegen.

  1. Es durchläuft auch geerbte Eigenschaften: Zunächst sollten alle Erweiterungen des Array.prototype durch Verwendung von Object.defineProperty() gemacht worden sein und ihr enumerable-Deskriptor sollte auf false gesetzt sein. Jede Bibliothek, die dies nicht tut, sollte überhaupt nicht verwendet werden.
  2. Eigenschaften, die Sie später in die Vererbungskette hinzufügen, werden ebenfalls gezählt: Beim Durchführen von Array-Subklassen durch Object.setPrototypeOf oder durch die Klassen extend. Sie sollten wieder Object.defineProperty() verwenden, das standardmäßig die Deskriptoren der Eigenschaften writable, enumerable und configurable auf false setzt. Sehen wir uns hier ein Beispiel zur Array-Subklassifizierung an...

    function Stack(...a){ var stack = new Array(...a); Object.setPrototypeOf(stack, Stack.prototype); return stack; } Stack.prototype = Object.create(Array.prototype); // jetzt hat stack vollen Zugriff auf Array-Methoden. Object.defineProperty(Stack.prototype,"constructor",{value:Stack}); // jetzt ist Stack ein richtiger Konstruktor Object.defineProperty(Stack.prototype,"peak",{value: function(){ // fügen Sie "nur" Stack-Methoden dem Stack.prototype hinzu. 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 sparse Arrays iterieren, die von Zeit zu Zeit benötigt werden. Dies ist einer der wichtigsten Leistungstricks, die man kennen sollte. Lassen Sie uns ein Beispiel sehen. Wir werden über ein sparse Array iterieren.

    var a = []; a[0] = "null"; a[10000000] = "zehn Millionen"; console.time("for-Schleife auf Array a:"); for(var i=0; i < a.length; i++) a[i] && console.log(a[i]); console.timeEnd("for-Schleife auf Array a:"); console.time("for in-Schleife auf Array a:"); for(var i in a) a[i] && console.log(a[i]); console.timeEnd("for in-Schleife auf 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 möchten wir bei einer Array-Iteration nur über das Array selbst iterieren. Und obwohl du selbst nichts zum Array hinzufügen möchtest, könnte deine Bibliothek oder dein Framework etwas hinzufügen.

Beispiel:

Array.prototype.hithere = 'hithere';

var array = [1, 2, 3];
for (let el in array){
    // die hithere-Eigenschaft wird ebenfalls iteriert
    console.log(el);
}
  1. for...in-Schleifen garantieren keine spezifische Iterationsreihenfolge. Obwohl diese 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, die noch nicht zugewiesen wurden.

Beispiel:

const arr = []; 
arr[3] = 'foo';   // das 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 undefined-Elemente an
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

console.log('\n');

// For-In ignoriert die undefined-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