Wenn ich ein Objekt wie dieses erstelle:
var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
Wird das resultierende Objekt immer so aussehen?
{ prop1 : "Foo", prop2 : "Bar" }
Das heißt, werden die Eigenschaften in der Reihenfolge sein, in der ich sie hinzugefügt habe?
javascript
object
Mellowsoon
quelle
quelle
for-in
,Object.keys
) müssen es nicht (offiziell) unterstützen, aber es gibt jetzt Ordnung. (Inoffiziell: Firefox, Chrome und Edge folgen alle der angegebenen Reihenfolge, auch in for-in und Object.keys, wo sie nicht offiziell verpflichtet sind: jsfiddle.net/arhbn3k2/1 )Antworten:
Die Iterationsreihenfolge für Objekte folgt seit ES2015 einem bestimmten Regelwerk , folgt jedoch (immer) nicht der Einfügereihenfolge . Einfach ausgedrückt ist die Iterationsreihenfolge eine Kombination aus der Einfügereihenfolge für Zeichenfolgenschlüssel und der aufsteigenden Reihenfolge für nummerähnliche Schlüssel:
Die Verwendung eines Arrays oder eines
Map
Objekts kann ein besserer Weg sein, um dies zu erreichen.Map
teilt einige Ähnlichkeiten mitObject
und garantiert, dass die Schlüssel ausnahmslos in der Reihenfolge des Einfügens iteriert werden :Hinweis: Die Reihenfolge der Eigenschaften in Objekten wurde vor ES2015 überhaupt nicht garantiert. Definition eines Objekts aus ECMAScript Third Edition (pdf) :
quelle
JA (für nicht ganzzahlige Schlüssel).
Die meisten Browser iterieren Objekteigenschaften wie folgt:
Einige ältere Browser kombinieren die Kategorien 1 und 2 und wiederholen alle Schlüssel in der Einfügereihenfolge. Wenn Ihre Schlüssel möglicherweise als Ganzzahlen analysiert werden, sollten Sie sich nicht auf eine bestimmte Iterationsreihenfolge verlassen.
Die Einfügereihenfolge der aktuellen Sprachspezifikation (seit ES2015) bleibt erhalten, außer bei Schlüsseln, die als Ganzzahlen analysiert werden (z. B. "7" oder "99"), bei denen das Verhalten zwischen den Browsern variiert. Beispielsweise berücksichtigt Chrome / V8 die Einfügereihenfolge nicht, wenn die Tasten als numerisch analysiert 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 durch vorhandenes Verhalten gesteuert wird und nicht umgekehrt. Weitere Informationen zu dieser Abwärtskompatibilitäts-Denkweise finden Sie unter http://code.google.com/p/v8/issues/detail?id=164 , einem Chrome-Fehler, der die Entwurfsentscheidungen für das Verhalten der Chrome-Iterationsreihenfolge ausführlich behandelt . Gemäß einem der (eher meinungsgebundenen) Kommentare zu diesem Fehlerbericht:
quelle
createFragment
API verlässt sich bereits darauf ... 🤔Die Eigenschaftsreihenfolge in normalen Objekten ist ein komplexes Thema in Javascript.
Während in ES5 explizit keine Reihenfolge angegeben wurde, hat ES2015 in bestimmten Fällen eine Reihenfolge. Gegeben ist folgendes Objekt:
Dies führt in der folgenden Reihenfolge (in bestimmten Fällen):
Somit gibt es 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.
Die Frage ist, für welche Methoden diese Reihenfolge in der ES2015-Spezifikation garantiert ist.
Die folgenden Methoden garantieren die angezeigte Reihenfolge:
Die folgenden Methoden / Schleifen garantieren überhaupt keine Bestellung:
Fazit: Auch in ES2015 sollten Sie sich nicht auf die Eigenschaftsreihenfolge normaler Objekte in Javascript verlassen. Es ist fehleranfällig. Verwenden Sie
Map
stattdessen.quelle
Zum Zeitpunkt des Schreibens gaben die meisten Browser Eigenschaften in der Reihenfolge zurück, in der sie eingefügt wurden, aber es war ausdrücklich kein garantiertes Verhalten, daher sollte man sich nicht darauf verlassen.
In der ECMAScript-Spezifikation heißt es:
In ES2015 und höher werden jedoch nicht ganzzahlige Schlüssel in Einfügereihenfolge zurückgegeben.
quelle
Diese ganze Antwort steht im Zusammenhang mit der Einhaltung von Spezifikationen, nicht mit dem, was ein Motor zu einem bestimmten Zeitpunkt oder in der Vergangenheit tut.
Im Allgemeinen nein
Die eigentliche Frage ist sehr vage.
In welchem Kontext?
Die Antwort lautet: Es hängt von einer Reihe von Faktoren ab. Im Allgemeinen nein .
Manchmal ja
Hier können Sie sich auf die Reihenfolge der Eigenschaftsschlüssel für Plain verlassen
Objects
:Object.getOwnPropertyNames()
,Reflect.ownKeys()
,Object.getOwnPropertySymbols(O)
In allen Fällen umfassen diese Methoden nicht aufzählbare Eigenschaftsschlüssel und Bestellschlüssel, wie von angegeben
[[OwnPropertyKeys]]
(siehe unten). Sie unterscheiden sich in der Art der Schlüsselwerte, die sie enthalten (String
und / oderSymbol
).String
Enthält in diesem Zusammenhang ganzzahlige Werte.Object.getOwnPropertyNames(O)
Gibt
O
dieString
Eigenschaften mit eigenen Schlüsseln ( Eigenschaftsnamen ) zurück.Reflect.ownKeys(O)
Gibt
O
die eigenen Eigenschaften mitString
und ohneSymbol
Schlüssel zurück.Object.getOwnPropertySymbols(O)
Gibt
O
dieSymbol
Eigenschaften mit eigenen Schlüsseln zurück.[[OwnPropertyKeys]]
Die Reihenfolge ist im Wesentlichen: ganzzahlig
Strings
in aufsteigender Reihenfolge, nicht ganzzahligStrings
in Erstellungsreihenfolge, Symbole in Erstellungsreihenfolge. Abhängig davon, 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:
Map
Wenn Sie an geordneten Karten interessiert sind, sollten Sie den
Map
in ES2015 eingeführten Typ anstelle von einfach verwendenObjects
.quelle
In modernen Browsern können Sie die
Map
Datenstruktur anstelle eines Objekts verwenden.Entwickler Mozilla> Karte
quelle
In ES2015 ist dies der Fall, aber nicht so, wie Sie vielleicht denken
Die Reihenfolge der Schlüssel in einem Objekt wurde erst in ES2015 garantiert. Es wurde implementierungsdefiniert.
Doch in ES2015 in wurde angegeben. Wie viele Dinge in JavaScript wurde dies aus Kompatibilitätsgründen durchgeführt und spiegelte im Allgemeinen einen bestehenden inoffiziellen Standard bei den meisten JS-Engines wider (wobei Sie wissen, wer eine Ausnahme darstellt).
Die Reihenfolge wird in der Spezifikation unter der abstrakten Operation OrdinaryOwnPropertyKeys definiert , die alle Methoden zum Iterieren über die eigenen Schlüssel eines Objekts unterstützt. Umschrieben lautet die Reihenfolge wie folgt:
Alle ganzzahligen Index Tasten (Sachen wie
"1123"
,"55"
usw.) in numerischer Reihenfolge aufsteigend.Alle Zeichenfolgenschlüssel, die keine ganzzahligen Indizes sind, in der Reihenfolge ihrer Erstellung (älteste zuerst).
Alle Symbolschlüssel in der Reihenfolge ihrer Erstellung (älteste zuerst).
Es ist albern zu sagen, dass die Reihenfolge unzuverlässig ist - es ist zuverlässig, es ist wahrscheinlich nicht das, was Sie wollen, und moderne Browser implementieren diese Reihenfolge korrekt.
Einige Ausnahmen umfassen Methoden zum Auflisten geerbter Schlüssel, z. B. die
for .. in
Schleife. Diefor .. in
Schleife garantiert keine Reihenfolge gemäß der Spezifikation.quelle
Ab ES2015 ist die Eigenschaftsreihenfolge für bestimmte Methoden garantiert, die über Eigenschaften iterieren. aber nicht andere . Leider werden im Allgemeinen am häufigsten Methoden verwendet, für die keine Bestellung garantiert ist:
Object.keys
,Object.values
,Object.entries
for..in
SchleifenJSON.stringify
Aber, wie der ES2020, Eigentum , um für diese bisher nicht vertrauenswürdig Methoden werden durch die Spezifikation garantiert wird in dem gleichen deterministisch werden iteriert wie die andere, aufgrund zum fertigen Vorschlag: für-in Mechanik .
Genau wie bei den Methoden mit einer garantierten Iterationsreihenfolge (wie
Reflect.ownKeys
undObject.getOwnPropertyNames
) werden auch die zuvor nicht angegebenen Methoden in der folgenden Reihenfolge iteriert:Dies ist, was so ziemlich jede Implementierung bereits tut (und dies seit vielen Jahren tut), aber der neue Vorschlag hat es offiziell gemacht.
Obwohl die aktuelle Spezifikation für ... in Iterationsreihenfolge " fast völlig nicht spezifiziert , sind echte Engines tendenziell konsistenter:"
Da jede Implementierung bereits vorhersehbar über Eigenschaften iteriert, kann sie in die Spezifikation aufgenommen werden, ohne die Abwärtskompatibilität zu beeinträchtigen.
Es gibt einige seltsame Fälle, über die sich Implementierungen derzeit nicht einig sind, und in solchen Fällen wird die resultierende Reihenfolge weiterhin nicht spezifiziert. Damit die Bestellung der Immobilie garantiert wird :
quelle
Wie bereits erwähnt, haben Sie keine Garantie für die Reihenfolge, wenn Sie die Eigenschaften eines Objekts durchlaufen. Wenn Sie eine geordnete Liste mit mehreren Feldern benötigen, habe ich vorgeschlagen, ein Array von Objekten zu erstellen.
Auf diese Weise können Sie eine reguläre for-Schleife verwenden und die Einfügereihenfolge festlegen. Sie können dann die Array-Sortiermethode verwenden, um diese bei Bedarf in ein neues Array zu sortieren.
quelle
Ich habe es gerade auf die harte Tour herausgefunden.
Bei Verwendung von Reagieren mit Redux wird der Statuscontainer, dessen Schlüssel ich durchlaufen möchte, um untergeordnete Elemente zu generieren, bei jeder Änderung des Speichers aktualisiert (gemäß den Unveränderlichkeitskonzepten von Redux).
Also, um zu nehmen, habe
Object.keys(valueFromStore)
ich verwendetObject.keys(valueFromStore).sort()
, so dass ich zumindest jetzt eine alphabetische Reihenfolge für die Schlüssel habe.quelle
Aus dem JSON-Standard :
(Hervorhebung von mir).
Nein, Sie können die Bestellung nicht garantieren.
quelle