Domanda

Ok, quindi su una pagina web ho un oggetto JavaScript che sto usando come array associativo. Questo esiste staticamente in un blocco di script quando la pagina viene caricata:

var salesWeeks = {
    "200911" : ["11 / 2009", "Fiscal 2009"],
    "200910" : ["10 / 2009", "Fiscal 2009"],
    "200909" : ["09 / 2009", "Fiscal 2009"],
    "200908" : ["08 / 2009", "Fiscal 2009"],
    "200907" : ["07 / 2009", "Fiscal 2009"],
    "200906" : ["06 / 2009", "Fiscal 2009"],
    "200905" : ["05 / 2009", "Fiscal 2009"],
    "200904" : ["04 / 2009", "Fiscal 2009"],
    "200903" : ["03 / 2009", "Fiscal 2009"],
    "200902" : ["02 / 2009", "Fiscal 2009"],
    "200901" : ["01 / 2009", "Fiscal 2009"],
    "200852" : ["52 / 2008", "Fiscal 2009"],
    "200851" : ["51 / 2008", "Fiscal 2009"]
};

L'ordine delle coppie chiave / valore è intenzionale, poiché sto trasformando l'oggetto in una casella di selezione HTML come questa:

<select id="ddl_sw" name="ddl_sw">
<option value="">== SELECT WEEK ==</option>
<option value="200911">11 / 2009 (Fiscal 2009)</option>
<option value="200910">10 / 2009 (Fiscal 2009)</option>
<option value="200909">09 / 2009 (Fiscal 2009)</option>
<option value="200908">08 / 2009 (Fiscal 2009)</option>
<option value="200907">07 / 2009 (Fiscal 2009)</option>
<option value="200906">06 / 2009 (Fiscal 2009)</option>
<option value="200905">05 / 2009 (Fiscal 2009)</option>
<option value="200904">04 / 2009 (Fiscal 2009)</option>
<option value="200903">03 / 2009 (Fiscal 2009)</option>
<option value="200902">02 / 2009 (Fiscal 2009)</option>
<option value="200901">01 / 2009 (Fiscal 2009)</option>
<option value="200852">52 / 2008 (Fiscal 2009)</option>
<option value="200851">51 / 2008 (Fiscal 2009)</option>
</select>

... con un codice simile al seguente (estratto da una funzione):

var arr = [];
arr.push(
    "<select id=\"ddl_sw\" name=\"ddl_sw\">" +
    "<option value=\"\">== SELECT WEEK ==</option>"
);

for(var key in salesWeeks)
{
    arr.push(
        "<option value=\"" + key + "\">" +
        salesWeeks[key][0] + " (" + salesWeeks[key][1] + ")" +
        "<\/option>"
    );
}

arr.push("<\/select>");

return arr.join("");

Tutto funziona perfettamente in IE, FireFox e Opera.

Tuttavia, in Chrome, l'ordine risulta strano:

<select id="ddl_sw" name="ddl_sw">
<option value="">== SELECT WEEK ==</option>
<option value="200852">52 / 2008 (Fiscal 2009)</option>
<option value="200908">08 / 2009 (Fiscal 2009)</option>
<option value="200906">06 / 2009 (Fiscal 2009)</option>
<option value="200902">02 / 2009 (Fiscal 2009)</option>
<option value="200907">07 / 2009 (Fiscal 2009)</option>
<option value="200904">04 / 2009 (Fiscal 2009)</option>
<option value="200909">09 / 2009 (Fiscal 2009)</option>
<option value="200903">03 / 2009 (Fiscal 2009)</option>
<option value="200905">05 / 2009 (Fiscal 2009)</option>
<option value="200901">01 / 2009 (Fiscal 2009)</option>
<option value="200910">10 / 2009 (Fiscal 2009)</option>
<option value="200911">11 / 2009 (Fiscal 2009)</option>
<option value="200851">51 / 2008 (Fiscal 2009)</option>
</select>

NOTA: questo ordine, sebbene strano, non cambia ai successivi aggiornamenti. È sempre in questo ordine.

Quindi, cosa sta facendo Chrome? Qualche ottimizzazione su come elabora il ciclo?

In primo luogo, sbaglio a fare affidamento sull'ordine in cui le coppie chiave / valore sono dichiarate in qualsiasi array associativo?

Non l'ho mai messo in discussione prima, ho solo pensato che l'ordine sarebbe rimasto perché questa tecnica ha sempre funzionato per me negli altri browser. Ma suppongo di non aver mai visto da nessuna parte affermare che l'ordine è garantito. Forse non lo è?

Qualsiasi approfondimento sarebbe fantastico. Grazie.

È stato utile?

Soluzione

Pensa a un array associativo come un sacco di carta in cui sono collocate tutte le coppie chiave-valore. Quando raggiungi la tua mano nel sacco per guardare le coppie (come nel caso del ... in loop), l'ordine in cui le incontri è casuale per tutti gli scopi.

Se vuoi vederli in un ordine specifico, dovrai estrarre le chiavi in ??un array e ordinarle. Quindi attraversa l'array, utilizzando le chiavi che incontri per indicizzare l'array associativo.

Altri suggerimenti

L'ordine in cui gli elementi sono memorizzati in un array associativo non è garantito. Dovrai ordinare il tuo output in modo esplicito.

Come dicono le altre risposte, l'ordine in cui le proprietà di un oggetto sono ripetute non è definito nelle specifiche, anche se i principali browser le ripetono tutte nell'ordine definito.

Chrome li enumererà anche in ordine, se tutte le proprietà dell'oggetto contengono valori primitivi. John Resig fornisce maggiori dettagli sul comportamento di Chrome qui (sotto "per l'ordine dei loop"): http://ejohn.org/blog/javascript-in-chrome/

Come sottolineato, il comportamento di Chrome è perfettamente valido.

Questo è un buon caso in cui alcuni pensieri OO possono aiutare. Vuoi davvero un array associativo o solo un elenco di oggetti?

var salesWeeks = [
    ["200911", "11 / 2009", "Fiscal 2009"],
    ...
]
...
for(var key in salesWeeks)
{
    arr.push(
        "<option value=\"" + salesWeeks[key][0] + "\">" +
        salesWeeks[key][1] + " (" + salesWeeks[key][2] + ")" +
        "<\/option>"
    );
}

Penso che ti servirebbe meglio (per quelli che hanno sostenuto una sorta di sorta, l'ordine è già definito - perché vuoi fare un lavoro extra?)

@curtainDog: NO! NO! L'uso di "for .. in" con gli oggetti Array in JavaScript non è corretto: l'intero punto della maggior parte delle risposte qui è che "for .. in" non garantisce alcun ordine. Inoltre, "for .. in" prenderà le proprietà dal prototipo del costruttore di un oggetto e non eseguirà l'iterazione su chiavi inesistenti.

@Samnan: la specifica dice semplicemente che l'ordine di iterazione non è garantito; questo significa che i browser sono liberi di iterare in ordine, in ordine di inserimento, in ordine casuale o comunque. È proprio come una tabella di hash: pensala come casuale, anche se capita di apparire in un ordine apparente.

Sono abbastanza sicuro che la maggior parte dei browser cerca "for..in" con gli oggetti Array e scorre in ordine numerico in modo che le cose non si rompano; tuttavia, non sta realmente facendo ciò che la maggior parte delle persone che lo usano in quel modo pensa che stia facendo, e dovrebbe essere evitato a meno che tu non abbia specificamente bisogno dell'iterazione di tipo oggetto .

Non è una buona pratica ma ...

Se aggiungi uno spazio al valore chrome non considererà value un numero e non li ordinerà per valore.

Esempio:

<select>
  <option value=" 3">Third</option>
  <option value=" 1">First</option>
  <option value=" 2">Second</option>
</select>

Il lato positivo è che non devi aggiungere e quindi rimuovere i caratteri alfabetici dall'ID come qualcuno ha suggerito (non ricordare se in questo o in altri post con domande simili), potresti facilmente tagliarlo ma la maggior parte delle volte il lo spazio viene semplicemente ignorato e se li pubblichi o li ottieni in un altro file, vedranno semplicemente il valore intero e non lo spazio.

Contrariamente a tutte le altre risposte, è Certamente UN ERRORE IN CROMO

Il motivo:

Se la struttura dei dati è un sacco di carta come Barry ha detto allora:

I valori devono essere sempre randimizzati. Questo non è il caso di Chrome

Se la struttura dei dati è sequenziale, allora:

I valori devono essere nella sequenza in cui vengono aggiunti alla struttura

Mentre altri browser seguono il secondo approccio, Chrome non ne segue nessuno e non c'è ancora alcuna spiegazione di quale sia l'ordinamento che Chrome compensa per la struttura dei dati mentre vi si accede.

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