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?

10voto

matpop Punkte 1870

Außerdem harmoniert die Art und Weise, wie for, in Arrays behandelt (d.h. wie jedes andere JavaScript-Objekt) nicht mit anderen beliebten Sprachen aufgrund der Semantik nicht.

// C#
char[] a = new char[] {'A', 'B', 'C'};
foreach (char x in a) System.Console.Write(x); //Ausgabe: "ABC"

// Java
char[] a = {'A', 'B', 'C'};
for (char x : a) System.out.print(x);          //Ausgabe: "ABC"

// PHP
$a = array('A', 'B', 'C');
foreach ($a as $x) echo $x;                    //Ausgabe: "ABC"

// JavaScript
var a = ['A', 'B', 'C'];
for (var x in a) document.write(x);            //Ausgabe: "012"

0 Stimmen

Das Argument hier ist, dass es schlecht ist, anders zu sein?

0 Stimmen

@LeeGoddard überhaupt nicht, ich weise nur darauf hin, dass normalerweise man für...in verwendet, um die "Werte" zu iterieren, nicht die "Schlüssel". Das Verhalten von JS ist keine schlechte Sache, es kann nur für viele Entwickler aus anderen beliebten Programmiersprachen kontraintuitiv sein, die den Fehler zunächst nicht verstehen und dann möglicherweise in diesem Zusammenhang lieber kein for...in verwenden möchten. Das ist alles, was die Antwort aufzeigt, es summiert sich als ein Nachteil, aber natürlich kann man darüber diskutieren.

0 Stimmen

@matpoop - Vive la différence! Grüße aus dem ehemaligen kommunistischen Osten.

8voto

Pierz Punkte 5458

Ein wichtiger Aspekt ist, dass for...in nur über Eigenschaften eines Objekts iteriert, die ihr enumerierbares Eigenschaftsattribut auf true gesetzt haben. Wenn man also versucht, über ein Objekt mit for...in zu iterieren, können beliebige Eigenschaften verpasst werden, wenn ihr enumerierbares Eigenschaftsattribut falsch ist. Es ist durchaus möglich, das enumerierbare Eigenschaftsattribut für normale Array-Objekte zu ändern, so dass bestimmte Elemente nicht aufgezählt werden. Im Allgemeinen neigen die Eigenschaftsattribute dazu, auf Funktions-eigenschaften innerhalb eines Objekts zuzutreffen.

Man kann den Wert des enumerierbaren Eigenschaftsattributs einer Eigenschaft überprüfen, indem man:

myobject.propertyIsEnumerable('myproperty')

Oder um alle vier Eigenschaftsattribute zu erhalten:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

Dies ist eine Funktion, die in ECMAScript 5 verfügbar ist - in früheren Versionen war es nicht möglich, den Wert des enumerierbaren Eigenschaftsattributs zu ändern (es war immer auf true gesetzt).

8voto

dc1 Punkte 81

Zusätzlich zu den anderen Problemen ist die "for..in"-Syntax wahrscheinlich langsamer, weil der Index eine Zeichenkette und nicht ein Integer ist.

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'

0 Stimmen

Vermutlich spielt das keine große Rolle. Array-Elemente sind Eigenschaften eines auf einem Array basierenden oder einem Array-ähnlichen Objekts, und alle Objekteigenschaften haben Zeichenschlüssel. Es sei denn, Ihr JS-Motor optimiert es auf irgendeine Weise, selbst wenn Sie eine Zahl verwendet haben, würde sie am Ende für den Lookup in eine Zeichenfolge umgewandelt werden.

0 Stimmen

Unabhängig von Leistungsproblemen, wenn Sie neu in JavaScript sind, verwenden Sie var i in a und erwarten, dass der Index eine Ganzzahl ist, dann wird das Ausführen von etwas wie a[i+offset] = Werte vollkommen falsch platzieren ("1" + 1 == "11").

8voto

Ricardo Punkte 89

Das for/in funktioniert mit zwei Arten von Variablen: Hashtabellen (assoziative Arrays) und Arrays (nicht-assoziativ).

JavaScript wird automatisch feststellen, wie es durch die Elemente geht. Wenn Sie also wissen, dass Ihr Array wirklich nicht-assoziativ ist, können Sie for (var i=0; i<=arrayLen; i++) verwenden und die automatische Detektionsiteration überspringen.

Aber meiner Meinung nach ist es besser, for/in zu verwenden, der für die Autoerkennung erforderliche Prozess ist sehr gering.

Eine richtige Antwort darauf hängt davon ab, wie die Browser den JavaScript-Code analysieren/interpretieren. Es kann sich zwischen Browsern ändern.

Ich kann keine anderen Zwecke für das Nichtverwenden von for/in finden;

//Nicht-assoziativ
var arr = ['a', 'b', 'c'];
for (var i in arr)
   alert(arr[i]);

//Assoziativ
var arr = {
   item1 : 'a',
   item2 : 'b',
   item3 : 'c'
};

for (var i in arr)
   alert(arr[i]);

2 Stimmen

für ... in funktioniert mit Objekten. Es gibt keine automatische Erkennung.

7voto

JAL Punkte 20777

Weil es über Eigenschaften iterieren wird, die Objekten in der Prototypenkette gehören, wenn Sie nicht darauf achten.

Sie können for.. in verwenden, stellen Sie einfach sicher, dass Sie jede Eigenschaft mit hasOwnProperty überprüfen.

2 Stimmen

Nicht genug - es ist völlig in Ordnung, beliebige benannte Eigenschaften zu Array-Instanzen hinzuzufügen, und diese werden true von hasOwnProperty() Überprüfungen zurückgeben.

0 Stimmen

Guter Punkt, danke. Ich war noch nie dumm genug, um das mit einem Array selbst zu tun, also habe ich das noch nie in Betracht gezogen!

1 Stimmen

@Pointy Ich habe dies nicht getestet, aber vielleicht kann dies durch Verwendung eines isNaN-Checks für jeden Eigenschaftsnamen überwunden werden.

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