Question L'ordre de propriété d'objet de garantie JavaScript est-il valide?


Si je crée un objet comme celui-ci:

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

L'objet résultant toujours ressemble à ca?

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

Autrement dit, les propriétés seront-elles dans le même ordre que je les ai ajoutées?


430
2018-04-02 20:54


origine


Réponses:


Non, l'ordre des propriétés dans les objets n'est pas garanti en JavaScript; vous devez utiliser un Array.

Définition d'un objet à partir de ECMAScript Troisième édition (pdf):

4.3.3 Objet

Un objet est un membre de   type Objet. C'est une collection non ordonnée de propriétés dont chacun   contient une valeur primitive, un objet ou   fonction. Une fonction stockée dans un   la propriété d'un objet est appelé   méthode.

Depuis ECMAScript 2015, en utilisant la Map objet pourrait être une alternative. UNE Map partage quelques similitudes avec un Object et garantit la commande des clés:

Une mappe itère ses éléments dans l'ordre d'insertion, tandis que l'ordre d'itération n'est pas spécifié pour les objets.


345
2018-04-02 20:56



Les spécifications linguistiques actuelles: techniquement, l'ordre n'est pas spécifié.

Navigateurs actuels: order est préservé avec l'exception majeure des clés comme "7" qui analysent comme des entiers et sont traitées différemment par Chrome / V8.

Future Language Spec (> ES2015): Généralement, vous pouvez vous attendre à ce que les choses commandées aujourd'hui ne deviennent pas désordonnées. De nouvelles API garantissent la commande; les API existantes sont difficiles à changer. Voir la réponse de JMM pour plus de détails.

Le meilleur lien ci-dessous se trouve dans le commentaire de Tim Down:

http://code.google.com/p/v8/issues/detail?id=164

Ce bogue couvre en détail les décisions de conception impliquées dans la mise en œuvre de la commande de clés par Chrome. On retient que pour les clés de chaîne qui n'analysent pas un entier (ie "a" ou "b", mais pas "3"), les clés sont imprimées dans l'ordre d'insertion sur tous les principaux navigateurs et bien que ce comportement ne soit pas "normalisé", il EST considéré comme un problème de compatibilité ascendante important par les fournisseurs de navigateurs. À utiliser à vos risques et périls.

Selon l’un des commentaires (plutôt d’opinion):

Les normes suivent toujours les mises en œuvre, d'où provient XHR, et Google fait la même chose en implémentant Gears, puis       embrassant des fonctionnalités HTML5 équivalentes. La bonne solution consiste à avoir ECMA formellement       incorporer le comportement standard de facto dans la prochaine révision de la spécification.

Si vous comptez sur l'ordre d'insertion, vous êtes en dehors de la spécification ECMAScript, mais dans la norme de facto du comportement commun du navigateur tant que vos clés ne sont pas analysées sous forme d'entiers.


105
2018-04-21 17:10



Au moment de la rédaction de cet article, la plupart des navigateurs renvoyaient des propriétés dans le même ordre qu’ils avaient été insérées, mais ce comportement n’était pas garanti de manière explicite.

le Spécification ECMAScript l'habitude de dire:

La mécanique et l'ordre de l'énumération des propriétés ... ne sont pas spécifiés.

Toutefois, dans ES2015 et versions ultérieures, les clés non entières seront renvoyées dans l'ordre d'insertion.


62
2018-04-02 20:56



L'ordre des propriétés dans les objets normaux est un sujet complexe en Javascript.

Alors que dans ES5 aucun ordre n'a été explicitement spécifié, ES2015 a un ordre dans certains cas. L'objet suivant est l'objet:

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},
});

Cela entraîne l'ordre suivant (dans certains cas):

Object {
  0: 0,
  1: "1",
  2: "2",
  b: "b",
  a: "a",
  Symbol(): "sym"
}
  1. clés de type entier dans l'ordre croissant
  2. touches normales dans l'ordre d'insertion
  3. Symboles dans l'ordre d'insertion

Ainsi, il y a trois segments, qui peuvent modifier l'ordre d'insertion (comme dans l'exemple). Et les clés de type entier ne collent pas du tout à l'ordre d'insertion.

La question est, pour quelles méthodes cette commande est garantie dans la spécification ES2015?

Les méthodes suivantes garantissent l'ordre indiqué:

  • Object.assign
  • Object.defineProperties
  • Object.getOwnPropertyNames
  • Object.getOwnPropertySymbols
  • Reflect.ownKeys

Les méthodes / boucles suivantes ne garantissent aucun ordre:

  • Object.keys
  • pour..in
  • JSON.parse
  • JSON.stringify

Conclusion: Même dans ES2015, vous ne devriez pas vous fier à l’ordre de propriété des objets normaux en Javascript. Il est sujet aux erreurs. Utilisation Map au lieu.


45
2017-07-06 07:38



Toute cette réponse est dans le contexte de la conformité des spécifications, pas ce que n'importe quel moteur fait à un moment particulier ou historiquement.

Généralement, non

La question réelle est très vague.

les propriétés seront dans le même ordre que je les ai ajoutées

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 de clé de propriété pour la plaine Objects:

  • Moteur conforme à la norme ES2015
  • Propres propriétés
  • 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 indiqué par [[OwnPropertyKeys]] (voir ci-dessous). Ils diffèrent par le type de valeurs clés qu'ils incluent (String et / ou Symbol). Dans ce contexte String inclut des valeurs entières.

Object.getOwnPropertyNames(O)

Résultats Ode propre String-Clé propriétés (noms de propriété).

Reflect.ownKeys(O)

Résultats Ode propre String- et Symbol-Clé propriétés.

Object.getOwnPropertySymbols(O)

Résultats Ode propre Symbol-Clé propriétés.

[[OwnPropertyKeys]]

L'ordre est essentiellement: entier Strings dans l'ordre croissant, non-entier Strings dans l'ordre de création, symboles dans l'ordre de création. Selon la fonction invoquée, 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:

  1. ... chaque clé de propriété P de O [l'objet itéré] qui est un index entier, dans l'ordre d'index numérique croissant

  2. ... chaque clé de propriété P de O c'est une chaîne mais n'est pas un index entier, dans l'ordre de création de propriété

  3. ... chaque clé de propriété P de O c'est un symbole, dans l'ordre de la création de la propriété

Map

Si vous êtes intéressé par les cartes ordonnées, vous devriez envisager d'utiliser Map type introduit dans ES2015 au lieu de plaine Objects.


35
2017-08-21 21:15



Dans les navigateurs modernes, vous pouvez utiliser le Map structure de données au lieu d'un objet.

Développeur mozilla> Carte 

Un objet Map peut itérer ses éléments dans l'ordre d'insertion ...


6
2018-06-02 01:22



Comme d'autres l'ont indiqué, 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.

var myarr = [{somfield1: 'x', somefield2: 'y'},
{somfield1: 'a', somefield2: 'b'},
{somfield1: 'i', somefield2: 'j'}];

De cette façon, vous pouvez utiliser une boucle régulière et avoir l'ordre d'insertion. Vous pouvez ensuite utiliser la méthode de tri Array pour la trier dans un nouveau tableau si nécessaire.


3
2018-01-27 19:09



Du Norme JSON:

Un objet est un non ordonné collection de zéro ou plusieurs paires nom / valeur, où un nom est une chaîne et une valeur est une chaîne, un nombre, un booléen, un null, un objet ou un tableau.

(emphase mienne).

Donc, non, vous ne pouvez pas garantir la commande.


-4
2018-04-02 20:59