Si je crée un objet comme celui-ci:
var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
L'objet résultant ressemblera-t-il toujours à ceci?
{ prop1 : "Foo", prop2 : "Bar" }
Autrement dit, les propriétés seront-elles dans le même ordre que je les ai ajoutées?
javascript
object
mellowsoon
la source
la source
for-in
,Object.keys
) n'ont pas à le supporter (officiellement), mais il y a de l' ordre maintenant. (Officiellement: Firefox, Chrome et Edge suivent tous l'ordre spécifié même dans for-in et Object.keys, où ils ne sont pas officiellement tenus de: jsfiddle.net/arhbn3k2/1 )Réponses:
L'ordre d'itération des objets suit un certain ensemble de règles depuis ES2015, mais il ne suit pas (toujours) l'ordre d'insertion . Autrement dit, l'ordre d'itération est une combinaison de l'ordre d'insertion pour les clés de chaînes et de l'ordre croissant pour les clés de type numérique:
L'utilisation d'un tableau ou d'un
Map
objet peut être un meilleur moyen d'y parvenir.Map
partage certaines similitudes avecObject
et garantit les clés à itérer par ordre d'insertion , sans exception:Remarque: l'ordre des propriétés dans les objets n'était pas du tout garanti avant ES2015. Définition d'un objet à partir d' ECMAScript troisième édition (pdf) :
la source
OUI (pour les clés non entières).
La plupart des navigateurs parcourent les propriétés des objets comme suit:
Certains navigateurs plus anciens combinent les catégories # 1 et # 2, itérant toutes les clés dans l'ordre d'insertion. Si vos clés peuvent être analysées sous forme d'entiers, il est préférable de ne pas s'appuyer sur un ordre d'itération spécifique.
L' ordre d'insertion de la spécification de langue actuelle (depuis ES2015) est conservé, sauf dans le cas des clés qui analysent en tant qu'entiers (par exemple, «7» ou «99»), où le comportement varie d'un navigateur à l'autre. Par exemple, Chrome / V8 ne respecte pas l'ordre d'insertion lorsque les touches sont analysées en numérique.
Ancienne spécification de langue (avant ES2015) : L'ordre d'itération était techniquement indéfini, mais tous les principaux navigateurs respectaient le comportement ES2015.
Notez que le comportement ES2015 était un bon exemple de la spécification de langue entraînée par le comportement existant, et non l'inverse. Pour mieux comprendre cet état d'esprit de compatibilité descendante, consultez http://code.google.com/p/v8/issues/detail?id=164 , un bogue Chrome qui couvre en détail les décisions de conception derrière le comportement de l'ordre d'itération de Chrome. . Selon l'un des commentaires (plutôt avisés) sur ce rapport de bogue:
la source
createFragment
repose déjà sur cela ... 🤔L'ordre des propriétés dans les objets normaux est un sujet complexe en Javascript.
Alors que dans ES5 explicitement aucune commande n'a été spécifiée, ES2015 a une commande dans certains cas. Étant donné l'objet suivant:
Il en résulte l'ordre suivant (dans certains cas):
Ainsi, il y a trois segments, qui peuvent modifier l'ordre d'insertion (comme cela s'est produit dans l'exemple). Et les clés de type entier ne respectent pas du tout l'ordre d'insertion.
La question est de savoir pour quelles méthodes cette commande est garantie dans la spécification ES2015.
Les méthodes suivantes garantissent l'ordre indiqué:
Les méthodes / boucles suivantes garantissent aucun ordre du tout:
Conclusion: Même dans ES2015, vous ne devez pas vous fier à l'ordre des propriétés des objets normaux en Javascript. Il est sujet aux erreurs. Utilisez
Map
plutôt.la source
Au moment de la rédaction de ce document, la plupart des navigateurs renvoyaient des propriétés dans le même ordre que celui où elles avaient été insérées, mais ce comportement n'était explicitement pas garanti et n'aurait donc pas dû être invoqué.
La spécification ECMAScript disait:
Cependant, dans ES2015 et les versions ultérieures, les clés non entières seront renvoyées dans l'ordre d'insertion.
la source
Toute cette réponse se situe dans le contexte de la conformité aux spécifications, et non à ce que fait un moteur à un moment donné ou historiquement.
En règle générale, non
La vraie question est très vague.
Dans quel contexte?
La réponse est: cela dépend d'un certain nombre de facteurs. En général, non .
Parfois oui
Voici où vous pouvez compter sur l'ordre des clés de propriété pour plain
Objects
:Object.getOwnPropertyNames()
,Reflect.ownKeys()
,Object.getOwnPropertySymbols(O)
Dans tous les cas, ces méthodes incluent des clés de propriété non énumérables et des clés de commande comme spécifié par
[[OwnPropertyKeys]]
(voir ci-dessous). Ils diffèrent par le type de valeurs clés qu'ils incluent (String
et / ouSymbol
). Dans ce contexte,String
comprend des valeurs entières.Object.getOwnPropertyNames(O)
Renvoie
O
les propriétés àString
clé propre ( noms de propriété ).Reflect.ownKeys(O)
Renvoie
O
les propriétés propresString
etSymbol
saisies.Object.getOwnPropertySymbols(O)
Renvoie
O
lesSymbol
propriétés propres de .[[OwnPropertyKeys]]
L'ordre est essentiellement: de type entier
Strings
dans l'ordre croissant, non de type entierStrings
dans l'ordre de création, Symboles dans l'ordre de création. Selon la fonction qui l'invoque, certains de ces types peuvent ne pas être inclus.La langue spécifique est que les clés sont retournées dans l'ordre suivant:
Map
Si vous êtes intéressé par les cartes ordonnées, vous devriez envisager d'utiliser le
Map
type introduit dans ES2015 au lieu de plainObjects
.la source
Dans les navigateurs modernes, vous pouvez utiliser la
Map
structure de données au lieu d'un objet.Développeur mozilla> Carte
la source
Dans ES2015, c'est le cas, mais pas à ce que vous pourriez penser
L'ordre des clés dans un objet n'était pas garanti avant ES2015. Il était défini par l'implémentation.
Cependant, dans ES2015 en a été spécifié. Comme beaucoup de choses en JavaScript, cela a été fait à des fins de compatibilité et reflète généralement une norme non officielle existante parmi la plupart des moteurs JS (avec vous-savez-qui étant une exception).
L'ordre est défini dans la spécification, sous l'opération abstraite OrdinaryOwnPropertyKeys , qui sous-tend toutes les méthodes d'itération sur les propres clés d'un objet. Paraphrasé, l'ordonnance est la suivante:
Tous les index entier clés ( des choses comme
"1123"
,"55"
, etc.) dans l' ordre numérique croissant.Toutes les clés de chaîne qui ne sont pas des indices entiers, par ordre de création (du plus ancien au plus ancien).
Toutes les touches de symboles, par ordre de création (du plus ancien au plus ancien).
Il est idiot de dire que la commande n'est pas fiable - elle est fiable, ce n'est probablement pas ce que vous voulez, et les navigateurs modernes implémentent correctement cette commande.
Certaines exceptions incluent les méthodes d'énumération des clés héritées, telles que la
for .. in
boucle. Lafor .. in
boucle ne garantit pas l'ordre selon les spécifications.la source
Depuis ES2015, l'ordre des propriétés est garanti pour certaines méthodes qui itèrent sur les propriétés. mais pas les autres . Malheureusement, les méthodes dont la commande n'est pas garantie sont généralement les plus utilisées:
Object.keys
,Object.values
,Object.entries
for..in
bouclesJSON.stringify
Mais, à partir d'ES2020, l'ordre des propriétés pour ces méthodes auparavant non fiables sera garanti par la spécification à réitérer de la même manière déterministe que les autres, en raison de la proposition finale : la mécanique for-in .
Tout comme avec les méthodes qui ont un ordre d'itération garanti (comme
Reflect.ownKeys
etObject.getOwnPropertyNames
), les méthodes non spécifiées précédemment seront également itérées dans l'ordre suivant:C'est déjà ce que font pratiquement toutes les mises en œuvre (et ce depuis de nombreuses années), mais la nouvelle proposition l'a officialisée.
Bien que la spécification actuelle laisse pour ... dans l'ordre d'itération " presque totalement non spécifié , les moteurs réels ont tendance à être plus cohérents:"
Étant donné que chaque implémentation itère déjà de manière prévisible sur les propriétés, elle peut être ajoutée à la spécification sans rompre la compatibilité descendante.
Il y a quelques cas étranges sur lesquels les implémentations ne sont pas d' accord actuellement , et dans de tels cas, l'ordre résultant ne sera pas spécifié. Pour que la propriété soit garantie :
la source
Comme d'autres l'ont dit, vous n'avez aucune garantie quant à l'ordre lorsque vous parcourez les propriétés d'un objet. Si vous avez besoin d'une liste ordonnée de plusieurs champs, j'ai suggéré de créer un tableau d'objets.
De cette façon, vous pouvez utiliser une boucle for régulière et avoir l'ordre d'insertion. Vous pouvez ensuite utiliser la méthode de tri Array pour trier cela dans un nouveau tableau si nécessaire.
la source
Je viens de découvrir cela à la dure.
En utilisant React avec Redux, le conteneur d'état dont je veux parcourir les clés afin de générer des enfants est actualisé à chaque changement de magasin (selon les concepts d'immuabilité de Redux).
Ainsi, pour prendre
Object.keys(valueFromStore)
j'ai utiliséObject.keys(valueFromStore).sort()
, de sorte que j'ai au moins maintenant un ordre alphabétique pour les touches.la source
De la norme JSON :
(c'est moi qui souligne).
Donc, non, vous ne pouvez pas garantir la commande.
la source