JavaScript garantisce l’ordine delle proprietà dell’object?

Se creo un object come questo:

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

L’object risultante sarà sempre simile a questo?

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

Cioè, le proprietà saranno nello stesso ordine in cui le ho aggiunte?

No, l’ordine delle proprietà negli oggetti non è garantito in JavaScript; è necessario utilizzare una Array .

Definizione di un object da ECMAScript Third Edition (pdf) :

4.3.3 Oggetto

Un object è un membro del tipo Object. È una raccolta non ordinata di proprietà ognuna delle quali contiene un valore, un object o una funzione primitivi. Una funzione memorizzata in una proprietà di un object è chiamata metodo.

Dal momento che ECMAScript 2015 , l’utilizzo dell’object Map potrebbe essere un’alternativa. Una Map condivide alcune somiglianze con un Object e garantisce l’ordine delle chiavi :

Una mappa itera i suoi elementi nell’ordine di inserimento, mentre l’ordine di iterazione non è specificato per gli oggetti.

Current Language Spec : tecnicamente, l’ordine non è specificato.

Browser correnti : l’ordine viene preservato con l’eccezione principale di tasti come “7” che analizzano come numeri interi e vengono gestiti in modo diverso da Chrome / V8.

Future Language Spec (> ES2015) : In genere, ci si può aspettare che le cose ordinate oggi non diventino non ordinate. Le nuove API garantiranno l’ordine; le API esistenti sono difficili da modificare. Vedi la risposta di JMM per maggiori dettagli.

Il miglior link qui sotto è nel commento di Tim Down:

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

Questo bug illustra in dettaglio le decisioni di progettazione coinvolte per l’implementazione di chiavi di Chrome da parte di Chrome. Un take-away è che per i tasti stringa che non analizzano un intero (cioè “a” o “b”, ma NON “3”), i tasti sono stampati in ordine di inserimento su tutti i principali browser e mentre questo comportamento non è “standardizzato”, è considerato un problema di retrocompatibilità significativo da parte dei produttori di browser. Utilizzare a proprio rischio.

Per uno dei commenti (piuttosto supponenti):

Gli standard seguono sempre le implementazioni, da qui nasce XHR e Google fa la stessa cosa implementando Gears e adottando quindi funzionalità HTML5 equivalenti. La soluzione corretta è che l’ECMA incorpori formalmente il comportamento standard de facto nel prossimo giro di specifiche.

Se si fa affidamento sull’ordine di inserimento, si è fuori dalle specifiche ECMAScript, ma all’interno dello standard di fatto del comportamento del browser comune fino a quando le chiavi non vengono analizzate come numeri interi .

Al momento della scrittura, la maggior parte dei browser restituiva le proprietà nello stesso ordine in cui erano state inserite, ma non era un comportamento esplicitamente garantito, quindi non ci si doveva fidare.

Le specifiche ECMAScript usate per dire:

La meccanica e l’ordine di enumerazione delle proprietà … non è specificato.

Tuttavia in ES2015 e in seguito le chiavi non intero saranno restituite in ordine di inserimento.

L’ordine delle proprietà in oggetti normali è un argomento complesso in Javascript.

Mentre in ES5 esplicitamente non è stato specificato alcun ordine, ES2015 ha un ordine in alcuni casi. Dato è il seguente object:

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

Ciò risulta nel seguente ordine (in alcuni casi):

 Object { 0: 0, 1: "1", 2: "2", b: "b", a: "a", Symbol(): "sym" } 
  1. tasti di tipo intero in ordine crescente
  2. chiavi normali in ordine di inserimento
  3. Simboli nell’ordine di inserimento

Pertanto, ci sono tre segmenti, che possono alterare l’ordine di inserimento (come è successo nell’esempio). E le chiavi di tipo intero non si attaccano affatto all’ordine di inserimento.

La domanda è, per quali metodi questo ordine è garantito nelle specifiche ES2015?

I seguenti metodi garantiscono l’ordine mostrato:

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

I seguenti metodi / loop non garantiscono alcun ordine:

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

Conclusione: anche in ES2015 non devi fare affidamento sull’ordine di proprietà degli oggetti normali in Javascript. È sobject a errori. Utilizza invece Map .

Tutta questa risposta è nel contesto della conformità delle specifiche, non di quello che qualsiasi motore fa in un determinato momento o storicamente.

Generalmente, no

La domanda reale è molto vaga.

le proprietà saranno nello stesso ordine in cui le ho aggiunte

In quale contesto?

La risposta è: dipende da una serie di fattori. In generale, no .

A Volte si

Qui puoi contare sull’ordine delle chiavi di proprietà per Objects semplici:

  • Motore conforms ES2015
  • Proprieta ‘
  • Object.getOwnPropertyNames() , Reflect.ownKeys() , Object.getOwnPropertySymbols(O)

In tutti i casi, questi metodi includono chiavi di proprietà non enumerabili e chiavi di ordine specificate da [[OwnPropertyKeys]] (vedere di seguito). Differiscono nel tipo di valori chiave che includono ( String e / o Symbol ). In questo contesto, String include valori interi.

Object.getOwnPropertyNames(O)

Restituisce le proprietà personalizzate di String ( nomi delle proprietà ) di O.

Reflect.ownKeys(O)

Restituisce le proprie proprietà String – e Symbol -keyed.

Object.getOwnPropertySymbols(O)

Restituisce le proprietà personalizzate con il tasto O Symbol .

[[OwnPropertyKeys]]

L’ordine è essenzialmente: Strings tipo intero in ordine ascendente, Strings non integer nell’ordine di creazione, simboli nell’ordine di creazione. A seconda di quale funzione invoca questo, alcuni di questi tipi potrebbero non essere inclusi.

La lingua specifica è che le chiavi vengono restituite nel seguente ordine:

  1. … ogni chiave di proprietà P di O [l’object che viene iterato] che è un indice intero, in ordine di indice numerico crescente

  2. … ogni propria chiave di proprietà P di O che è una stringa ma non è un indice intero, nell’ordine di creazione della proprietà

  3. … ciascuna chiave di proprietà P di O che è un simbolo, nell’ordine di creazione della proprietà

Map

Se sei interessato alle mappe ordinate dovresti prendere in considerazione l’uso del tipo di Map introdotto in ES2015 invece di Objects semplici.

Nei browser moderni è ansible utilizzare la struttura dei dati della Map anziché un object.

Sviluppatore mozilla> Mappa

Un object Mappa può iterare i suoi elementi nell’ordine di inserimento …

Come altri hanno affermato, non si ha alcuna garanzia per quanto riguarda l’ordine quando si itera sulle proprietà di un object. Se hai bisogno di un elenco ordinato di più campi, ti suggerisco di creare una serie di oggetti.

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

In questo modo puoi usare un ciclo for regolare e avere l’ordine di inserimento. È quindi ansible utilizzare il metodo di ordinamento Array per ordinare questo in un nuovo array, se necessario.

Dallo standard JSON :

Un object è un insieme non ordinato di zero o più coppie nome / valore, dove un nome è una stringa e un valore è una stringa, un numero, un booleano, un null, un object o un array.

(sottolineatura mia).

Quindi, no, non puoi garantire l’ordine.