Pregunta

Ok, en una página web, tengo un objeto JavaScript que estoy usando como una matriz asociativa. Esto existe estáticamente en un bloque de script cuando se carga la página:

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

El orden de los pares clave / valor es intencional, ya que estoy convirtiendo el objeto en un cuadro de selección HTML como este:

<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 código que se ve así (recortado de una función):

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

Todo esto funciona bien en IE, Firefox y Opera.

Sin embargo, en Chrome, el pedido resulta extraño:

<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: Este orden, aunque extraño, no cambia en las actualizaciones posteriores. Siempre está en este orden.

Entonces, ¿qué está haciendo Chrome? ¿Alguna optimización en cómo procesa el ciclo?

En primer lugar, ¿me equivoco al confiar en el orden en que los pares clave / valor se declaran en any matriz asociativa?

Nunca lo cuestioné antes, simplemente asumí que la orden se mantendría porque esta técnica siempre me ha funcionado en los otros navegadores. Pero supongo que nunca lo he visto en ninguna parte declarar que el pedido está garantizado. Tal vez no lo es?

Cualquier idea sería genial. Gracias.

¿Fue útil?

Solución

Piense en una matriz asociativa como una bolsa de papel en la que se colocan todos los pares clave-valor. Al meter la mano en el saco para mirar los pares (como con el bucle for ... in), el orden en que los encuentra es aleatorio a todos los efectos prácticos.

Si desea verlos en un orden específico, deberá extraer las claves en una matriz y ordenarlas. Luego camine a través de la matriz, usando las teclas que encuentre para indexar en la matriz asociativa.

Otros consejos

No se garantiza el orden en que los elementos se almacenan en una matriz asociativa. Tendrá que ordenar su salida explícitamente.

Como dicen las otras respuestas, el orden en el que se iteran las propiedades de un objeto no está definido en la especificación, a pesar de que los principales navegadores los iteran en el orden definido.

Chrome también los enumerará en orden, si todas las propiedades del objeto contienen valores primitivos. John Resig da más detalles sobre el comportamiento de Chrome aquí (en " para orden de bucle "): http://ejohn.org/blog/javascript-in-chrome/

Como se señaló, el comportamiento de Chrome es perfectamente válido.

Este es un buen caso de donde algo de pensamiento OO puede ayudar. ¿Realmente quieres una matriz asociativa o simplemente una 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>"
    );
}

creo que te serviría mejor (para aquellos que abogan por algún tipo de orden, el orden ya está definido: ¿por qué quieres hacer un trabajo extra?)

@curtainDog: ¡NO! ¡NO! Usando & # 8220; para ... en & # 8221; con los objetos de matriz en JavaScript es malo: el punto completo de la mayoría de las respuestas aquí es que & # 8220; para ... en & # 8221; No garantiza ningún pedido. Además, & # 8220; para ... en & # 8221; tomará propiedades del prototipo del constructor de un objeto y no iterará sobre claves inexistentes.

@Samnan: la especificación simplemente dice que el orden de iteración no está garantizado; Esto significa que los navegadores son libres de iterar en orden ordenado, en orden de inserción, en orden aleatorio, o de lo contrario pueden hacerlo. Es como una tabla hash: piense en ello como aleatorio, incluso si sale en un orden aparente.

Estoy bastante seguro de que la mayoría de los navegadores buscan & # 8220; por ... en & # 8221; con objetos Array e iterar en orden numérico para que las cosas no se rompan; sin embargo, en realidad no está haciendo lo que la mayoría de las personas que lo usan de esa manera piensan que está haciendo, y debe evitarse a menos que necesite específicamente la iteración de tipo objeto .

No es una buena práctica pero ...

Si agrega un espacio al valor, Chrome no considerará el valor como un número y no los ordenará por valor.

Ejemplo:

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

El lado bueno es que no tiene que agregar y luego eliminar los caracteres alfabéticos de la identificación como alguien sugirió (no recuerdo si en esta u otra publicación con una pregunta similar), podría recortarlo fácilmente, pero la mayoría de las veces el simplemente se ignora el espacio y si publica u obtiene esos en otro archivo, simplemente verán el valor entero, no el espacio.

Contrariamente a todas las otras respuestas, CIERTAMENTE ES UN ERROR EN EL CROMO

El motivo:

Si la estructura de datos es una bolsa de papel como dijo Barry entonces:

Los valores siempre deben ser randimizados. Este no es el caso en Chrome

Si la estructura de datos es secuencial, entonces:

Los valores deben estar en la secuencia en la que se agregan a la estructura

Mientras que otros navegadores siguen el segundo enfoque, Chrome sigue ninguno de los dos y todavía no hay una explicación de cuál es el orden de clasificación que Chrome compensa la estructura de datos mientras se accede.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top