Ordine degli elementi in & # 8220; per (& # 8230; in & # 8230;) & # 8221; ciclo continuo

StackOverflow https://stackoverflow.com/questions/280713

  •  07-07-2019
  •  | 
  •  

Domanda

Il " per ... in " loop in Javascript loop attraverso gli hashtables / elementi nell'ordine in cui sono dichiarati? Esiste un browser che non lo fa in ordine?
L'oggetto che desidero utilizzare verrà dichiarato una volta e non verrà mai modificato.

Supponiamo di avere:

var myObject = { A: "Hello", B: "World" };

E li uso ulteriormente in:

for (var item in myObject) alert(item + " : " + myObject[item]);

Posso aspettarmi 'A: " Ciao "' venire sempre prima di "B: " World "" nella maggior parte dei browser decenti?

È stato utile?

Soluzione

Citando John Resig :

  

Attualmente tutti i principali browser eseguono il ciclo delle proprietà di un oggetto nell'ordine in   che sono stati definiti. Anche Chrome fa questo, tranne un paio di casi. [...]   Questo comportamento viene esplicitamente lasciato non definito dalla specifica ECMAScript.   In ECMA-262, sezione 12.6.4:

     
    

La meccanica dell'enumerazione delle proprietà ... dipende dall'implementazione.

  
     

Tuttavia, le specifiche sono abbastanza diverse dall'implementazione. Tutte le implementazioni moderne   di ECMAScript scorre le proprietà dell'oggetto nell'ordine in cui sono state definite.   Per questo motivo il team di Chrome ha ritenuto che si trattasse di un bug e lo risolverà.

Tutti i browser rispettano l'ordine di definizione ad eccezione di Chrome e Opera che fanno per ogni nome di proprietà non numerico. In questi due browser le proprietà vengono tirate in ordine prima della prima proprietà non numerica (ciò ha a che fare con il modo in cui implementano le matrici). L'ordine è lo stesso anche per Object.keys .

Questo esempio dovrebbe chiarire cosa succede:

var obj = {
  "first":"first",
  "2":"2",
  "34":"34",
  "1":"1",
  "second":"second"
};
for (var i in obj) { console.log(i); };
// Order listed:
// "1"
// "2"
// "34"
// "first"
// "second"

I tecnicismi di questo sono meno importanti del fatto che ciò può cambiare in qualsiasi momento. Non fare affidamento sul fatto che le cose rimangano così.

In breve: Usa un array se l'ordine è importante per te.

Altri suggerimenti

Incontrarlo un anno dopo ...

È 2012 e i principali browser sono ancora diversi:

function lineate(obj){
    var arr = [], i;
    for (i in obj) arr.push([i,obj[i]].join(':'));
    console.log(arr);
}
var obj = { a:1, b:2, c:3, "123":'xyz' };
/* log1 */  lineate(obj);
obj.a = 4;
/* log2 */  lineate(obj);
delete obj.a;
obj.a = 4;
/* log3 */  lineate(obj);

gist o test nel browser corrente

Safari 5, Firefox 14

["a:1", "b:2", "c:3", "123:xyz"]
["a:4", "b:2", "c:3", "123:xyz"]
["b:2", "c:3", "123:xyz", "a:4"]

Chrome 21, Opera 12, Nodo 0.6, Firefox 27

["123:xyz", "a:1", "b:2", "c:3"]
["123:xyz", "a:4", "b:2", "c:3"]
["123:xyz", "b:2", "c:3", "a:4"]

IE9

[123:xyz,a:1,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 
[123:xyz,a:4,b:2,c:3] 

Dalle Specifiche del linguaggio ECMAScript , sezione 12.6.4 (su per .. in loop):

  

La meccanica dell'enumerazione delle proprietà dipende dall'implementazione. L'ordine di enumerazione è definito dall'oggetto.

E la sezione 4.3.3 (definizione di " Object "):

  

È una raccolta non ordinata di proprietà, ognuna delle quali contiene un valore, un oggetto o una funzione primitivi. Una funzione memorizzata in una proprietà di un oggetto è chiamata metodo.

Immagino che ciò significhi che non puoi fare affidamento sulle proprietà enumerate in un ordine coerente tra le implementazioni JavaScript. (Sarebbe comunque un cattivo stile fare affidamento su dettagli specifici di una lingua per l'implementazione.)

Se vuoi che il tuo ordine sia definito, dovrai implementare qualcosa che lo definisce, come una matrice di chiavi che ordini prima di accedere all'oggetto con esso.

Gli elementi di un oggetto che per / in enumera sono le proprietà che non hanno il flag DontEnum impostato. Lo standard ECMAScript, noto anche come Javascript, afferma esplicitamente che "Un oggetto è una raccolta non ordinata di proprietà" (vedi http://www.mozilla.org/js/language/E262-3 .pdf sezione 8.6).

Non sarà conforme agli standard (vale a dire sicuro) supporre che tutte le implementazioni di Javascript vengano enumerate in ordine di dichiarazione.

Anche l'ordine di iterazione è confuso rispetto all'eliminazione delle proprietà, ma in questo caso solo con IE.

var obj = {};
obj.a = 'a';
obj.b = 'b';
obj.c = 'c';

// IE allows the value to be deleted...
delete obj.b;

// ...but remembers the old position if it is added back later
obj.b = 'bb';
for (var p in obj) {
    alert(obj[p]); // in IE, will be a, bb, then c;
                   // not a, c, then bb as for FF/Chrome/Opera/Safari
}

Il desiderio di modificare le specifiche per correggere l'ordine di iterazione sembra essere piuttosto popolare tra gli sviluppatori se la discussione su http://code.google.com/p/v8/issues/detail?id=164 è un'indicazione.

in IE6, l'ordine non è garantito.

L'ordine non può essere considerato attendibile. Sia Opera che Chrome restituiscono l'elenco delle proprietà non ordinate.

<script type="text/javascript">
var username = {"14719":"A","648":"B","15185":"C"};

for (var i in username) {
  window.alert(i + ' => ' + username[i]);
}
</script>

Il codice sopra mostra B, A, C in Opera e C, A, B in Chrome.

Questo non risponde alla domanda di per sé, ma offre una soluzione al problema di base.

Supponendo che non si possa fare affidamento sull'ordine per preservarlo, perché non utilizzare una matrice di oggetti con chiave e valore come proprietà?

var myArray = [
    {
        'key'   : 'key1'
        'value' : 0
    },
    {
        'key'   : 'key2',
        'value' : 1
    } // ...
];

Ora spetta a te assicurarti che le chiavi siano univoche (supponendo che ciò sia importante anche per te. Inoltre, le modifiche di indirizzamento diretto e per (... in ...) ora restituiscono gli indici come " chiavi.

> console.log(myArray[0].key);
key1

> for (let index in myArray) {console.log(myArray[index].value);}
0
1
Vedi la penna per l'indirizzamento (... in ...) in ordine di JDQ ( @JDQ ) su CodePen .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top