Orden de elementos en un & # 8220; para (& # 8230; en & # 8230;) & # 8221; lazo

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

  •  07-07-2019
  •  | 
  •  

Pregunta

¿El " para ... en " bucle en Javascript bucle a través de las tablas / elementos hash en el orden en que se declaran? ¿Hay un navegador que no lo hace en orden?
El objeto que deseo usar se declarará una vez y nunca se modificará.

Supongamos que tengo:

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

Y los uso en:

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

¿Puedo esperar 'A: " Hola "' siempre antes de 'B: " Mundo "' en la mayoría de los navegadores decentes?

¿Fue útil?

Solución

Citando a John Resig :

  

Actualmente todos los principales navegadores recorren las propiedades de un objeto en el orden en   que fueron definidos Chrome también hace esto, excepto por un par de casos. [...]   Este comportamiento queda explícitamente indefinido por la especificación ECMAScript.   En ECMA-262, sección 12.6.4:

     
    

La mecánica de enumerar las propiedades ... depende de la implementación.

  
     

Sin embargo, la especificación es bastante diferente de la implementación. Todas las implementaciones modernas   de ECMAScript iteran a través de las propiedades del objeto en el orden en que fueron definidas.   Debido a esto, el equipo de Chrome ha considerado que esto es un error y lo corregirá.

Todos los navegadores respetan el orden de definición con la excepción de Chrome y Opera, que lo hacen para cada nombre de propiedad no numérico. En estos dos navegadores, las propiedades se extraen en orden antes de la primera propiedad no numérica (esto tiene que ver con la forma en que implementan las matrices). El orden es el mismo para Object.keys también.

Este ejemplo debe dejar claro lo que sucede:

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"

Los tecnicismos de esto son menos importantes que el hecho de que esto puede cambiar en cualquier momento. No confíe en que las cosas se mantengan de esta manera.

En resumen: Use una matriz si el orden es importante para usted.

Otros consejos

Topando esto un año después ...

Es 2012 y los principales navegadores aún difieren:

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 prueba en el navegador actual

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] 

De la especificación del lenguaje ECMAScript , sección 12.6.4 (en el bucle for .. in ):

  

La mecánica de enumerar las propiedades depende de la implementación. El orden de enumeración está definido por el objeto.

Y la sección 4.3.3 (definición de " Objeto "):

  

Es una colección desordenada de propiedades, cada una de las cuales contiene un valor primitivo, objeto o función. Una función almacenada en una propiedad de un objeto se llama método.

Supongo que eso significa que no puede confiar en las propiedades que se enumeran en un orden consistente en todas las implementaciones de JavaScript. (De todos modos, sería un mal estilo confiar en detalles específicos de la implementación de un idioma).

Si desea definir su orden, necesitará implementar algo que lo defina, como una matriz de claves que clasifique antes de acceder al objeto con él.

Los elementos de un objeto que para / in enumera son las propiedades que no tienen establecido el indicador DontEnum. El estándar ECMAScript, también conocido como Javascript, dice explícitamente que "Un objeto es una colección desordenada de propiedades". (ver http://www.mozilla.org/js/language/E262-3 .pdf sección 8.6).

No va a ser compatible con los estándares (es decir, seguro) asumir que todas las implementaciones de Javascript se enumerarán en orden de declaración.

El orden de iteración también se confunde con respecto a la eliminación de propiedades, pero en este 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
}

El deseo de cambiar las especificaciones para corregir el orden de iteración parece ser un deseo bastante popular entre los desarrolladores si la discusión en http://code.google.com/p/v8/issues/detail?id=164 es cualquier indicación.

en IE6, el pedido no está garantizado.

No se puede confiar en el pedido. Tanto Opera como Chrome devuelven la lista de propiedades desordenadas.

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

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

El código anterior muestra B, A, C en Opera y C, A, B en Chrome.

Esto no responde la pregunta per se, pero ofrece una solución al problema básico.

Suponiendo que no puede confiar en el orden para preservar, ¿por qué no utilizar una matriz de objetos con clave y valor como propiedades?

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

Ahora, depende de usted asegurarse de que las claves sean únicas (suponiendo que esto también sea importante para usted. Además, los cambios de direccionamiento directo y para (... en ...) ahora devuelve índices como ' teclas '.

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

> for (let index in myArray) {console.log(myArray[index].value);}
0
1
Vea el Pen para (... en ...) direccionamiento en orden por JDQ ( @JDQ ) en CodePen .

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