it-swarm.com.de

Elementreihenfolge in einer "for (… in ...)" Schleife

Schleifen die "for ... in" -Schleifen in Javascript die Hashtables/Elemente in der Reihenfolge, in der sie deklariert sind? Gibt es einen Browser, der dies nicht in Ordnung macht?
.__ Das Objekt, das ich verwenden möchte, wird einmalig deklariert und niemals geändert.

Angenommen, ich habe:

var myObject = { A: "Hello", B: "World" };

Und ich benutze sie weiter in:

for (var item in myObject) alert(item + " : " + myObject[item]);

Kann ich erwarten, dass "A:" Hello "" in den meisten anständigen Browsern immer vor "B:" World "" steht?

189
chakrit

Zitat John Resig :

Derzeit führen alle gängigen Browser die Eigenschaften eines Objekts in der Reihenfolge in .__ durch. welche sie definiert wurden. Chrome macht dies ebenfalls, mit Ausnahme einiger Fälle. [...] Dieses Verhalten wird von der ECMAScript-Spezifikation explizit undefiniert. In ECMA-262, Abschnitt 12.6.4:

Die Mechanik der Aufzählung der Eigenschaften ... hängt von der Implementierung ab.

Die Spezifikation unterscheidet sich jedoch stark von der Implementierung. Alle modernen Implementierungen von ECMAScript durchlaufen die Objekteigenschaften in der Reihenfolge, in der sie definiert wurden. Aus diesem Grund hat das Chrome-Team dies für einen Fehler gehalten und wird es beheben.

Alle Browser beachten die Definitionsreihenfolge mit Ausnahme von Chrome und Opera, die für jeden nicht numerischen Eigenschaftennamen gelten. In diesen beiden Browsern werden die Eigenschaften der ersten nicht numerischen Eigenschaft vorgezogen (dies hat mit der Implementierung von Arrays zu tun). Die Reihenfolge ist auch für Object.keys gleich.

Dieses Beispiel soll deutlich machen, was passiert: 

var obj = {
  "first":"first",
  "2":"2",
  "34":"34",
  "1":"1",
  "second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"

Die technischen Aspekte sind weniger wichtig als die Tatsache, dass sich dies jederzeit ändern kann. Verlassen Sie sich nicht darauf, dass die Dinge so bleiben.

Kurz gesagt: Verwenden Sie ein Array, wenn Ihnen die Reihenfolge wichtig ist.

200
Borgar

Dies ein Jahr später stoßen ...

Es ist 2012 und die wichtigsten Browser noch unterscheiden sich:

function lineate(obj){
    var arr = [], i;
    for (i in obj) arr.Push([i,obj[i]].join(':'));
    console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */  lineate(obj);
obj.a = 4;
/* log2 */  lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */  lineate(obj);

Gist oder Test im aktuellen Browser

Safari 5, Firefox 14

["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]

Chrome 21, Opera 12, Node 0.6, Firefox 27

["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]

IE9

[123:xyz,a:1,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
53
dvdrtrgn

Aus der ECMAScript-Sprachspezifikation , Abschnitt 12.6.4 (in der for .. in-Schleife):

Die Aufzählung der Eigenschaften hängt von der Implementierung ab. Die Reihenfolge der Aufzählung wird durch das Objekt festgelegt.

Und Abschnitt 4.3.3 (Definition von "Objekt"):

Es ist eine ungeordnete Sammlung von Eigenschaften, von denen jede einen primitiven Wert, ein Objekt oder eine Funktion enthält. Eine in einer Eigenschaft eines Objekts gespeicherte Funktion wird als Methode bezeichnet.

Das bedeutet, dass Sie sich nicht darauf verlassen können, dass die Eigenschaften in allen JavaScript-Implementierungen in einer konsistenten Reihenfolge aufgelistet werden. (Es wäre sowieso ein schlechter Stil, sich auf implementierungsspezifische Details einer Sprache zu verlassen.)

Wenn Sie möchten, dass Ihre Reihenfolge definiert wird, müssen Sie etwas implementieren, das sie definiert, beispielsweise ein Array von Schlüsseln, die Sie sortieren, bevor Sie auf das Objekt zugreifen.

26
Tomalak

Die Elemente eines Objekts, für das in/aufgezählt wird, sind die Eigenschaften, für die das DontEnum-Flag nicht festgelegt ist. Der Standard von ECMAScript, alias Javascript, besagt ausdrücklich, dass "ein Objekt eine ungeordnete Sammlung von Eigenschaften ist" (siehe http://www.mozilla.org/js/language/E262-3.pdf Abschnitt 8.6.

Es wird nicht normkonform (d. H. Sicher) sein, wenn alle Javascript-Implementierungen in Deklarationsreihenfolge aufgelistet werden.

10
Adam Wright

Die Iterationsreihenfolge wird auch in Bezug auf das Löschen von Eigenschaften verwechselt, jedoch in diesem Fall nur mit IE.

var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';

// IE allows the value to be deleted...
delete obj.b;

// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
    alert(obj[p]); // in IE, will be a, bb, then c;
                   // not a, c, then bb as for FF/Chrome/Opera/Safari
}

Der Wunsch, die Spezifikation zu ändern, um die Iterationsreihenfolge zu korrigieren, scheint unter den Entwicklern sehr beliebt zu sein, wenn die Diskussion unter http://code.google.com/p/v8/issues/detail?id=164 ist irgendein Hinweis.

4
Brett Zamir

in IE6 ist die Bestellung nicht garantiert. 

3
Ari

Der Bestellung kann nicht vertraut werden. Sowohl Opera als auch Chrome geben die Liste der Eigenschaften ungeordnet zurück.

<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};

for (var i in username) {
  window.alert(i + ' => ' + username[i]);
}
</script>

Der obige Code zeigt B, A, C in Opera und C, A, B in Chrome.

2
Kouber Saparev