Pergunta

Ok, então em uma página web, eu tenho um objeto JavaScript que estou usando como uma matriz associativa. Isso existe estaticamente em um bloco de script quando a página é carregada:

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"]
};

A ordem dos pares de chave / valor é intencional, como eu estou virando o objeto em uma caixa de seleção HTML como esta:

<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>

... com código parecido com este (snipped de uma função):

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("");

Esta tudo bem funciona no IE, Firefox e Opera.

No entanto, no Chrome, a ordem sai tudo estranho:

<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: Esta ordem, embora estranho, não muda em atualizações posteriores. É sempre nessa ordem.

Então, o que é Chrome fazendo? Alguns otimização na forma como ele processa o loop?

Em primeiro lugar, estou errado a contar com a ordem em que os pares de chave / valor são declaradas em qualquer matriz associativa?

Eu nunca questionei isso antes, eu só assumiu a ordem iria realizar, porque esta técnica sempre trabalhou para mim em outros navegadores. Mas eu suponho que eu nunca vi isso em nenhum lugar que a ordem é garantida. Talvez não?

Qualquer visão seria fantástico. Obrigado.

Foi útil?

Solução

Pense em um array associativo como um saco de papel para o qual todos os pares de valor-chave são colocados. Como você alcançar a sua mão no saco de olhar para os pares (como com o loop for ... in), a fim de que você encontrá-los é para todos os efeitos práticos aleatórios.

Se você quiser vê-los em uma ordem específica, você vai precisar para extrair as chaves em uma matriz e classificá-lo. Em seguida, atravessar a matriz, utilizando as teclas que você encontra para índice para a matriz associativa.

Outras dicas

A ordem em que os elementos são armazenados em uma matriz associativa não é garantida. Você vai ter que classificar sua saída explicitamente.

Como as outras respostas dizer, a ordem em que as propriedades de um objeto são iterados não está definido na especificação, embora os principais navegadores tudo iterate-los na ordem definida.

Chrome irá enumerar-los em ordem também, se todas as propriedades do objeto contém valores primitivos. John Resig dá mais detalhes sobre o comportamento do Chrome aqui (em "para a ordem de loop"): http://ejohn.org/blog/javascript-in-chrome/

Como apontado o comportamento do Chrome é perfeitamente válido.

Este é um bom exemplo de onde alguns pensamento OO pode ajudar. Você realmente quer uma matriz associativa ou apenas uma lista de objetos?

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

iria atendê-lo melhor, eu acho que (para aqueles que defendia alguma forma de classificar, a ordem já está definido - por que você quer fazer um trabalho extra)

@curtainDog: NÃO! NÃO! Usando “for .. in” com objetos de matriz em JavaScript é ruim - toda a ponto da maioria das respostas aqui é que “for .. in” não garante qualquer ordem. Além disso, “for .. in” vai agarrar propriedades de protótipo do construtor de um objeto e não irá iterar sobre as chaves inexistentes.

@Samnan: A especificação simplesmente diz que ordem de iteração não é garantida; Isto significa que os navegadores estão livres para percorrer na ordem de classificação, em ordem de inserção, em ordem aleatória, ou no entanto, mais eles maio. É como uma tabela hash -. Pensar nisso como aleatório, mesmo se acontecer de sair em alguma ordem aparente

Estou bastante certeza da maioria dos navegadores procurar “for..in” com objetos Array e iterate em ordem numérica para que as coisas não quebram; no entanto, não está realmente fazendo o que a maioria das pessoas que usam essa maneira acho que está fazendo, e ele deve ser evitado a menos que você especificamente precisa objeto do tipo iteração.

Não é uma verdadeira boa prática, mas ...

Se você adicionar um espaço para o valor cromo não irá considerar o valor de um número e não irá tipo-los por valor.

Exemplo:

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

O lado bom é que você não tem que adicionar e remover caracteres alfabéticos de ID como alguém sugeriu (não me lembro se neste ou em outro post com questão semelhante), você pode facilmente cortá-la, mas a maioria das vezes o espaço é simplesmente ignorado e se você postar ou obter aqueles para outro arquivo eles simplesmente verá o valor inteiro não o espaço.

Ao contrário de todas as outras respostas, é certamente um bug no CHROME

O motivo:

Se a estrutura de dados é um saco de papel como Barry disse em seguida:

Os valores devem ser sempre randimized. Este não é o caso em cromo

Se a estrutura de dados é sequencial, em seguida:

Os valores devem estar na ordem em que são adicionadas à estrutura

Enquanto outros navegadores seguem a segunda abordagem, cromo segue nenhum dos dois e ainda não existe uma explicação do que é o cromo ordem de classificação torna-se para a estrutura de dados enquanto ele é acessado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top