Garantiert JavaScript die Reihenfolge der Objekteigenschaften?

Lesezeit: 11 Minuten

Garantiert JavaScript die Reihenfolge der Objekteigenschaften
bald weich

Wenn ich ein Objekt wie dieses erstelle:

var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";

Wird das resultierende Objekt immer sieht aus wie das?

{ prop1 : "Foo", prop2 : "Bar" }

Das heißt, werden die Eigenschaften in der gleichen Reihenfolge angezeigt, in der ich sie hinzugefügt habe?

  • mögliches Duplikat von Elements order – for (… in …) loop in Javascript

    – Borgar

    7. Juni 2011 um 19:29 Uhr

  • auch relevant: Führt ES6 eine klar definierte Aufzählungsreihenfolge für Objekteigenschaften ein?

    – Bergi

    11. Dezember 2015 um 10:09 Uhr

  • Die hier akzeptierte Antwort ist nicht mehr korrekt. Aktuelle Antworten finden Sie hier.

    – TJ Crowder

    21. Mai 2017 um 15:19 Uhr

  • @TJCrowder Könnten Sie etwas näher darauf eingehen, warum die akzeptierte Antwort nicht mehr korrekt ist? Die Frage, die Sie verlinkt haben, scheint auf die Idee hinauszulaufen, dass die Reihenfolge der Eigenschaften immer noch nicht per Spezifikation garantiert ist.

    – null298

    2. November 2017 um 19:53 Uhr

  • @zero298: Die akzeptierte Antwort auf diese Frage beschreibt eindeutig die angegebenen Eigentumsordnung ab ES2015+. Legacy-Operationen (for-in, Object.keys) müssen es nicht (offiziell) unterstützen, aber da ist jetzt bestellen. (Inoffiziell: Firefox, Chrome und Edge folgen alle der angegebenen Reihenfolge, sogar in for-in und Object.keys, wo sie nicht offiziell dazu verpflichtet sind: jsfiddle.net/arhbn3k2/1)

    – TJ Crowder

    3. November 2017 um 8:57 Uhr

1646888113 812 Garantiert JavaScript die Reihenfolge der Objekteigenschaften
bpierre

Die Iterationsreihenfolge für Objekte folgt seit ES2015 bestimmten Regeln, aber es folgt nicht (immer) der Insertionsreihenfolge. Einfach ausgedrückt ist die Iterationsreihenfolge eine Kombination aus der Einfügungsreihenfolge für Zeichenfolgenschlüssel und der aufsteigenden Reihenfolge für zahlenähnliche Schlüssel:

// key order: 1, foo, bar
const obj = { "foo": "foo", "1": "1", "bar": "bar" }

Mit einem Array oder a Map Objekt kann ein besserer Weg sein, dies zu erreichen. Map teilt einige Ähnlichkeiten mit Object und garantiert, dass die Schlüssel in der Reihenfolge des Einfügens iteriert werdenohne Ausnahme:

Die Schlüssel in der Karte sind geordnet, die dem Objekt hinzugefügten Schlüssel jedoch nicht. Wenn es also durchlaufen wird, gibt ein Map-Objekt Schlüssel in der Reihenfolge des Einfügens zurück. (Beachten Sie, dass in der ECMAScript 2015-Spezifikation Objekte die Erstellungsreihenfolge für Zeichenfolgen- und Symbolschlüssel beibehalten, sodass das Durchlaufen eines Objekts mit z. B. nur Zeichenfolgenschlüsseln Schlüssel in der Reihenfolge des Einfügens ergeben würde.)

Beachten Sie, dass die Reihenfolge der Eigenschaften in Objekten vor ES2015 überhaupt nicht garantiert wurde. Definition eines Objekts aus ECMAScript Dritte Ausgabe (pdf):

4.3.3 Objekt

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

  • Das Verhalten von Ganzzahlschlüsseln ist nicht in allen Browsern konsistent. Einige ältere Browser iterieren ganzzahlige Schlüssel in der Reihenfolge der Einfügung (mit den Zeichenfolgenschlüsseln) und einige in aufsteigender Reihenfolge.

    – David Dopson

    29. Dezember 2019 um 0:13 Uhr

  • @DaveDopson – Richtig – veraltete Browser folgen nicht der aktuellen Spezifikation, da sie nicht aktualisiert werden.

    – TJ Crowder

    2. Januar 2020 um 8:46 Uhr

  • Ist “Ganzzahlschlüssel” richtig? Basierend auf meinen eingeschränkten Tests werden nur ganzzahlige Schlüssel / nicht negative ganzzahlige Schlüssel in aufsteigender Reihenfolge sortiert.

    – Zementblöcke

    6. Dezember 2021 um 18:48 Uhr

Garantiert JavaScript die Reihenfolge der Objekteigenschaften
David Dopson

YES (für nicht ganzzahlige Schlüssel).

Die meisten Browser iterieren Objekteigenschaften wie folgt:

  1. Integer-Schlüssel in aufsteigender Reihenfolge (und Zeichenfolgen wie “1”, die als Ints analysiert werden)
  2. Zeichenfolgenschlüssel, in der Reihenfolge der Einfügung (ES2015 garantiert dies und alle Browser entsprechen)
  3. Symbolnamen, in der Reihenfolge der Einfügung (ES2015 garantiert dies und alle Browser entsprechen)

Einige ältere Browser kombinieren die Kategorien Nr. 1 und Nr. 2 und iterieren alle Schlüssel in der Reihenfolge der Einfügung. Wenn Ihre Schlüssel möglicherweise als Ganzzahlen analysiert werden, ist es am besten, sich nicht auf eine bestimmte Iterationsreihenfolge zu verlassen.

Aktuelle Sprachspezifikation (seit ES2015) Die Einfügereihenfolge wird beibehalten, außer im Fall von Schlüsseln, die als Ganzzahlen analysiert werden (z. B. „7“ oder „99“), bei denen das Verhalten je nach Browser unterschiedlich ist. Beispielsweise berücksichtigt Chrome/V8 die Einfügungsreihenfolge nicht, wenn die Schlüssel als numerisch geparst werden.

Alte Sprachspezifikation (vor ES2015): Die Iterationsreihenfolge war technisch nicht definiert, aber alle gängigen Browser entsprachen dem ES2015-Verhalten.

Beachten Sie, dass das ES2015-Verhalten ein gutes Beispiel dafür war, dass die Sprachspezifikation von vorhandenem Verhalten gesteuert wird und nicht umgekehrt. Um ein tieferes Gefühl für diese Denkweise der Abwärtskompatibilität zu bekommen, siehe http://code.google.com/p/v8/issues/detail?id=164, ein Chrome-Fehler, der die Designentscheidungen hinter dem Verhalten der Iterationsreihenfolge von Chrome ausführlich behandelt. Laut einem der (ziemlich eigensinnigen) Kommentare zu diesem Fehlerbericht:

Standards folgen immer Implementierungen, daher kam XHR, und Google tut dasselbe, indem es Gears implementiert und dann die äquivalente HTML5-Funktionalität umarmt. Die richtige Lösung besteht darin, ECMA das De-facto-Standardverhalten formell in die nächste Version der Spezifikation integrieren zu lassen.

  • @BenjaminGruenbaum – das war genau mein Punkt. Ab 2014 hatten alle großen Anbieter eine gemeinsame Implementierung und daher werden die Standards schließlich folgen (dh im Jahr 2015).

    – David Dopson

    1. Oktober 2015 um 2:01 Uhr

  • Übrigens: Reagieren createFragment API setzt schon darauf… 🤔

    – mik01aj

    4. Juli 2016 um 15:44 Uhr


  • @BenjaminGruenbaum Ihr Kommentar ist falsch. In ES2015 wird die Bestellung nur für garantiert ausgewählt Methoden. Siehe Antwort von nach unter.

    – Piotr Dobrogost

    7. Oktober 2016 um 15:34 Uhr

  • @mik01aj willst du den Quellcode von React verlinken, der das tut? (Ja, ich bin faul)

    – José V

    12. Januar 2021 um 5:47 Uhr

  • @DaveDopson für Punkt 1. es ist nur nicht negativ Integer-Schlüssel richtig?

    – Arthur Carvalho

    10. Mai 2021 um 14:29 Uhr

Die Eigenschaftsreihenfolge in normalen Objekten ist ein komplexes Thema in JavaScript.

Während in ES5 ausdrücklich keine Reihenfolge angegeben wurde, definierte ES2015 in bestimmten Fällen eine Reihenfolge, und sukzessive Änderungen an der Spezifikation seitdem haben die Reihenfolge zunehmend definiert (ab ES2020 sogar die for-in Reihenfolge der Schleife). 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) folgende Reihenfolge:

Object {
  0: 0,
  1: "1",
  2: "2",
  b: "b",
  a: "a",
  m: function() {},
  Symbol(): "sym"
}

Die Reihenfolge für “eigene” (nicht geerbte) Eigenschaften ist:

  1. Integer-ähnliche Schlüssel in aufsteigender Reihenfolge
  2. Zeichenfolgenschlüssel in der Reihenfolge der Einfügung
  3. Symbole in der Reihenfolge der Einfügung

Somit gibt es drei Segmente, die die Einfügungsreihenfolge ä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 der Reihenfolge:

  • Objektzuweisung
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Reflect.ownKeys
  • JSON.parse
  • JSON.stringify

Ab ES2020 tun es alle anderen (einige in Spezifikationen zwischen ES2015 und ES2020, andere in ES2020), einschließlich:

  • Objekt.Schlüssel, Objekt.Einträge, Objekt.Werte, …
  • für in

Am schwierigsten festzunageln war for-in weil es in einzigartiger Weise geerbte Eigenschaften enthält. Dass geschah (in allen Ausnahmefällen) in ES2020. Die folgende Liste aus dem verlinkten (inzwischen abgeschlossenen) Angebot enthält die Grenzfälle, in denen die Reihenfolge nicht angegeben ist:

  • Weder das iterierte Objekt noch irgendetwas in seiner Prototypkette ist ein Proxy, ein typisiertes Array, ein Modul-Namespace-Objekt oder ein exotisches Host-Objekt.
  • Weder das Objekt noch irgendetwas in seiner Prototypkette ändert seinen Prototyp während der Iteration.
  • Weder das Objekt noch irgendetwas in seiner Prototypkette hat eine Eigenschaft, die während der Iteration gelöscht wird.
  • Nichts in der Prototypenkette des Objekts hat eine Eigenschaft, die während der Iteration hinzugefügt wird.
  • Bei keiner Eigenschaft des Objekts oder irgendetwas in seiner Prototypkette ändert sich die Aufzählbarkeit während der Iteration.
  • Keine nicht aufzählbare Eigenschaft überschattet eine aufzählbare.

Fazit: Auch in ES2015 sollte man sich nicht auf die Eigenschaftsreihenfolge normaler Objekte in JavaScript verlassen. Es ist fehleranfällig. Wenn Sie geordnete benannte Paare benötigen, verwenden Sie Map stattdessen wird nur die Anzeigenreihenfolge verwendet. Wenn Sie nur Ordnung brauchen, verwenden Sie ein Array oder Set (die auch eine reine Insertionsreihenfolge verwendet).

1646888113 749 Garantiert JavaScript die Reihenfolge der Objekteigenschaften
Alnitak

Zum Zeitpunkt des Schreibens gaben die meisten Browser Eigenschaften in der gleichen Reihenfolge zurück, in der sie eingefügt wurden, aber es war kein ausdrücklich garantiertes Verhalten, also hätte man sich nicht darauf verlassen sollen.

Die ECMAScript-Spezifikation pflegte zu sagen:

Die Mechanik und Reihenfolge der Aufzählung der Eigenschaften … ist nicht festgelegt.

In ES2015 und höher werden jedoch nicht ganzzahlige Schlüssel in der Reihenfolge der Einfügung zurückgegeben.

Garantiert JavaScript die Reihenfolge der Objekteigenschaften
JMM

Diese ganze Antwort bezieht sich auf die Spezifikationskonformität und nicht darauf, was eine Engine zu einem bestimmten Zeitpunkt oder in der Vergangenheit tut.

Generell nein

Die eigentliche Frage ist sehr vage.

werden die Eigenschaften in der gleichen Reihenfolge sein, in der ich sie hinzugefügt habe

In welchem ​​Kontext?

Die Antwort lautet: Es hängt von mehreren Faktoren ab. Im Allgemeinen, Nein.

Manchmal ja

Hier können Sie sich auf die Bestellung von Eigenschaftsschlüsseln für Plain verlassen Objects:

  • ES2015-konformer Motor
  • Eigene Immobilien
  • Object.getOwnPropertyNames(), Reflect.ownKeys(), Object.getOwnPropertySymbols(O)

In allen Fällen enthalten diese Methoden nicht aufzählbare Eigenschaftsschlüssel und Ordnungsschlüssel, wie von angegeben [[OwnPropertyKeys]] (siehe unten). Sie unterscheiden sich in der Art der enthaltenen Schlüsselwerte (String und/oder Symbol). In diesem Zusammenhang String enthält ganzzahlige Werte.

Object.getOwnPropertyNames(O)

Kehrt zurück Oist eigen String-keyed Eigenschaften (Eigenschaftsnamen).

Reflect.ownKeys(O)

Kehrt zurück Oist eigen String– und Symbol-verschlüsselte Eigenschaften.

Object.getOwnPropertySymbols(O)

Kehrt zurück Oist eigen Symbol-verschlüsselte Eigenschaften.

[[OwnPropertyKeys]]

Die Reihenfolge ist im Wesentlichen: ganzzahlig Strings in aufsteigender Reihenfolge, nicht ganzzahlig Strings in der Reihenfolge der Erstellung, Symbole in der Reihenfolge der Erstellung. Je nachdem, welche Funktion dies aufruft, sind einige dieser Typen möglicherweise nicht enthalten.

Die spezifische Sprache ist, dass Schlüssel in der folgenden Reihenfolge zurückgegeben werden:

  1. … jeder einen eigenen Eigenschaftsschlüssel P von O [the object being iterated] das ist ein ganzzahliger Index in aufsteigender numerischer Indexreihenfolge

  2. … jeder einen eigenen Eigenschaftsschlüssel P von O das ist ein String, aber kein ganzzahliger Index, in der Reihenfolge der Eigenschaftserstellung

  3. … jeder einen eigenen Eigenschaftsschlüssel P von O das ist ein Symbol in der Reihenfolge der Eigenschaftserstellung

Map

Wenn Sie an bestellten Karten interessiert sind, sollten Sie die Verwendung von in Betracht ziehen Map Typ eingeführt in ES2015 anstelle von Plain Objects.

1646888114 817 Garantiert JavaScript die Reihenfolge der Objekteigenschaften
Gemeinschaft

Ab ES2015 wird die Eigenschaftsreihenfolge für bestimmte Methoden garantiert, die Eigenschaften durchlaufen. aber nicht andere. Leider werden die Methoden, bei denen keine Bestellung garantiert ist, im Allgemeinen am häufigsten verwendet:

  • Object.keys, Object.values, Object.entries
  • for..in Schleifen
  • JSON.stringify

Aber ab ES2020 Eigentumsordnung für diese zuvor nicht vertrauenswürdigen Methoden Wille durch die Spezifikation garantiert werden auf die gleiche deterministische Weise wie die anderen iteriert werden, aufgrund von beendet Vorschlag: für-in mechanik.

Genau wie bei den Methoden, die eine garantierte Iterationsreihenfolge haben (wie Reflect.ownKeys und Object.getOwnPropertyNames), werden die zuvor nicht spezifizierten Methoden ebenfalls in der folgenden Reihenfolge durchlaufen:

  • Numerische Array-Schlüssel in aufsteigender numerischer Reihenfolge
  • Alle anderen Nicht-Symbol-Schlüssel in der Reihenfolge der Einfügung
  • Symbolschlüssel in der Reihenfolge der Einfügung

Das ist es, was so ziemlich jede Implementierung bereits tut (und das seit vielen Jahren), aber der neue Vorschlag hat es offiziell gemacht.

Obwohl die aktuelle Spezifikation für … in Iterationsreihenfolge “fast völlig unbestimmtechte Motoren sind tendenziell konsistenter:”

Der Mangel an Spezifität in ECMA-262 spiegelt nicht die Realität wider. In jahrelangen Diskussionen haben Implementierer festgestellt, dass es einige Einschränkungen für das Verhalten von for- gibt, denen jeder folgen muss, der Code im Web ausführen möchte.

Da jede Implementierung bereits vorhersagbar über Eigenschaften iteriert, kann sie in die Spezifikation aufgenommen werden, ohne die Abwärtskompatibilität zu beeinträchtigen.


Es gibt einige seltsame Fälle, die derzeit von Implementierungen ausgeführt werden nicht vereinbaren, und in solchen Fällen bleibt die resultierende Reihenfolge unbestimmt. Zur Eigentumsbestellung zu gewährleisten:

Weder das iterierte Objekt noch irgendetwas in seiner Prototypkette ist ein Proxy, ein typisiertes Array, ein Modul-Namespace-Objekt oder ein exotisches Host-Objekt.

Weder das Objekt noch irgendetwas in seiner Prototypkette ändert seinen Prototyp während der Iteration.

Weder das Objekt noch irgendetwas in seiner Prototypkette hat eine Eigenschaft, die während der Iteration gelöscht wird.

Nichts in der Prototypenkette des Objekts hat eine Eigenschaft, die während der Iteration hinzugefügt wird.

Bei keiner Eigenschaft des Objekts oder irgendetwas in seiner Prototypkette ändert sich die Aufzählbarkeit während der Iteration.

Keine nicht aufzählbare Eigenschaft überschattet eine aufzählbare.

1646888115 904 Garantiert JavaScript die Reihenfolge der Objekteigenschaften
Michel

In modernen Browsern können Sie die Map Datenstruktur statt Objekt.

Entwickler mozilla > Karte

Ein Map-Objekt kann seine Elemente in der Einfügereihenfolge iterieren…

986270cookie-checkGarantiert JavaScript die Reihenfolge der Objekteigenschaften?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy