Man hat mir gesagt, for...in
nicht mit Arrays in JavaScript zu verwenden. Warum nicht?
Das Argument hier ist, dass es schlecht ist, anders zu sein?
Man hat mir gesagt, for...in
nicht mit Arrays in JavaScript zu verwenden. Warum nicht?
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"
@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.
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).
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.
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]);
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.
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.
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!
@Pointy Ich habe dies nicht getestet, aber vielleicht kann dies durch Verwendung eines isNaN
-Checks für jeden Eigenschaftsnamen überwunden werden.
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ü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?
1 Stimmen
@MattDiPasquale - Ja, es ist umgekehrt, jedoch unter einer bekannten Grenze ermöglicht es eine optimale Verarbeitung, insbesondere in älteren Browsern, durch Iteration über einen bekannten Satz im Gegensatz zu einer unbekannten Satzlänge, indem die Grenze zuerst festgelegt wird. Es ist die Natur einer interpretierten Sprache.
0 Stimmen
@MarkSchultheiss Guter Kommentar. Man könnte die
for
-Schleife auch alsfor (var i = hColl.length; i--;) {}
schreiben, 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 das i im Cache, da es einen Unterschied macht und den Test vereinfacht. - je älter der Browser, desto größer der Unterschied zwischenfor
undwhile
IMMER den "i" Zähler im Cache speichern - und natürlich passt negativ nicht immer zur Situation und das Negative, währendobfuscate
den Code für einige Leute ein wenig verkompliziert. und beachten Sievar i = 1000; for (i; i; i--) {}
undvar b =1000 for (b; b--;) {}
wobei i von 1000 auf 1 und b von 999 auf 0 geht. - je älter der Browser, desto mehr neigt das while zur Leistungssteigerung.12 Stimmen
Sie können auch klug sein.
for(var i = 0, l = myArray.length; i < l; ++i) ...
ist die schnellste und beste Möglichkeit, die Sie mit einem Vorwärtsdurchlauf erhalten können.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 sind Mikro-Optimierungen. Wenn Sie sich unsicher sind, entscheiden Sie sich für lesbaren Code, nicht für eine stark 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 Schleifensteuerung.