Die Reihenfolge der Eigenschaften in normalen Objekten ist ein komplexes Thema in JavaScript.
Während in ES5 explizit keine Reihenfolge festgelegt wurde, definierte ES2015 eine Reihenfolge in bestimmten Fällen, und die nachfolgenden Änderungen der Spezifikation haben die Reihenfolge zunehmend definiert (ab ES2020 sogar die for-in
Schleifenanordnung). Gegeben ist das folgende Objekt:
const o = Object.create(null, {
m: {value: function() {}, enumerable: true},
"2": {value: "2", enumerable: true},
"b": {value: "b", enumerable: true},
0: {value: 0, enumerable: true},
[Symbol()]: {value: "sym", enumerable: true},
"1": {value: "1", enumerable: true},
"a": {value: "a", enumerable: true},
});
Daraus ergibt sich (in bestimmten Fällen) die folgende Reihenfolge:
Object {
0: 0,
1: "1",
2: "2",
b: "b",
a: "a",
m: function() {},
Symbol(): "sym"
}
Die Reihenfolge für "eigene" (nicht vererbte) Eigenschaften ist:
- Integer-ähnliche Schlüssel in aufsteigender Reihenfolge
- Zeichenkettenschlüssel in Einfügereihenfolge
- Symbole in Einfügereihenfolge
Es gibt also drei Segmente, die die Einfügereihenfolge ändern können (wie im Beispiel geschehen). Und ganzzahlige Schlüssel halten sich überhaupt nicht an die Einfügereihenfolge.
In ES2015 folgten nur bestimmte Methoden dieser Reihenfolge:
- Objekt.zuweisen
- Object.defineProperties
- Object.getOwnPropertyNames
- Object.getOwnPropertySymbols
- Reflect.ownKeys
- JSON.parse
- JSON.stringify
Ab ES2020 tun dies alle anderen (einige in den Spezifikationen zwischen ES2015 und ES2020, andere in ES2020), einschließlich:
- Object.keys, Object.entries, Object.values, ...
- für in
Am schwierigsten war es, die folgenden Punkte festzulegen for-in
weil sie als einzige vererbte Eigenschaften enthält. Das wurde getan (in allen Fällen mit Ausnahme von Randfällen) in ES2020. Die folgende Liste aus dem verlinkten (inzwischen abgeschlossenen) Vorschlag enthält die Randfälle, in denen die Reihenfolge nicht festgelegt ist:
- Weder das Objekt, das iteriert wird, noch irgendetwas in seiner Prototypenkette ist ein Proxy, ein typisiertes Array, ein Modul-Namespace-Objekt oder ein exotisches Host-Objekt.
- Weder das Objekt noch irgendetwas in seiner Prototypenkette ändert seinen Prototyp während der Iteration.
- Weder das Objekt noch irgendetwas in seiner Prototypenkette hat eine Eigenschaft, die während der Iteration gelöscht wird.
- In der Prototypenkette des Objekts wurde während der Iteration keine Eigenschaft hinzugefügt.
- Keine Eigenschaft des Objekts oder irgendetwas in seiner Prototypenkette ändert seine Aufzählbarkeit während der Iteration.
- Keine nicht aufzählbare Eigenschaft überschattet eine aufzählbare.
Schlussfolgerung: Auch in ES2015 sollte man sich nicht auf die Eigenschaftsreihenfolge von normalen Objekten in JavaScript verlassen. Sie ist anfällig für Fehler. Wenn Sie geordnete benannte Paare benötigen, verwenden Sie Map
die nur die Einfügereihenfolge verwendet. Wenn Sie nur die Reihenfolge benötigen, verwenden Sie ein Array oder Set
(die ebenfalls eine reine Einfügereihenfolge verwendet).
2 Stimmen
Mögliche Duplikate von Elemente ordnen - for (... in ...) Schleife in javascript
5 Stimmen
Auch relevant: Führt ES6 eine wohldefinierte Reihenfolge der Aufzählung für Objekteigenschaften ein?
9 Stimmen
Die akzeptierte Antwort ist hier nicht mehr zutreffend. Aktuelle Antworten finden Sie hier.
1 Stimmen
@T.J.Crowder Könnten Sie etwas näher darauf eingehen, warum die akzeptierte Antwort nicht mehr stimmt? Die Frage, die Sie verlinkt haben, scheint darauf hinauszulaufen, dass die Reihenfolge der Eigenschaften immer noch nicht per Spezifikation garantiert ist.
3 Stimmen
@zero298: Die akzeptierte Antwort auf diese Frage beschreibt eindeutig die angegeben Reihenfolge der Eigenschaften ab ES2015+. Legacy-Operationen (
for-in
,Object.keys
) müssen es nicht (offiziell) unterstützen, aber es gibt es jetzt bestellen. (Inoffiziell: Firefox, Chrome und Edge befolgen alle die angegebene Reihenfolge, selbst in for-in und Object.keys, wo dies offiziell nicht vorgeschrieben ist: jsfiddle.net/arhbn3k2/1 )0 Stimmen
HINWEIS:
delete obj1.prop1
garantiert auch nicht die Reihenfolge der Schlüssel - siehe developer.mozilla.org/de-US/docs/Web/JavaScript/Reference/0 Stimmen
Ist damit Ihre Frage beantwortet? Führt ES6 eine wohldefinierte Reihenfolge der Aufzählung für Objekteigenschaften ein?
2 Stimmen
Und jetzt, ab ES2020, sogar
for-in
hat eine definierte Reihenfolge; ich habe die diese Antwort mit dem aktuellen Stand der Dinge.