¿Cree usted que hay una gran diferencia en la…en y para los bucles? ¿Qué tipo de «para» preferís y por qué?

Supongamos que tenemos un array de arrays asociativos:

var myArray = [{'key': 'value'}, {'key': 'value1'}];

Por lo que podemos iterar:

for (var i = 0; i < myArray.length; i++)

Y:

for (var i in myArray)

No veo una gran diferencia. Hay problemas de rendimiento?

  • Tenga en cuenta que nosotros también, como de JS 1.6, tiene: myArray.forEach(callback[, thisarg]).
  • de la matriz.forEach es en realidad en ES5.
  • en un para-en el bucle usted necesita un condicional que se parece a esto: if(myArray.hasOwnProperty(i)){true}
  • ['foo', 'bar', 'baz'].forEach(function(element, index, array){ console.log(element, index, array); }); es ACEPTAR a utilizar casi todas partes, excepto en IE8 – y es, por mucho, el más elegante de la sintaxis
  • También hay for...of declaración en ECMAScript 6, por ejemplo: for (let i of myArray) console.log(i);
InformationsquelleAutor andrii | 2008-10-28

23 Comentarios

  1. 543

    La elección debe basarse en las que el idioma se entiende mejor.

    Una matriz se itera mediante:

    for (var i = 0; i < a.length; i++)
       //do stuff with a[i]

    Un objeto que se utiliza como un array asociativo se itera mediante:

    for (var key in o)
      //do stuff with o[key]

    A menos que tenga tierra, destrozando razones, se adhieren a la establecida patrón de uso.

    • Cabe mencionar que es una buena práctica utilizar para…con el filtrado de la instrucción if. No es un método práctico de Objeto «obj.hasOwnProperty(miembro)», que comprueba si un miembro que devuelve un iterador es en realidad miembro del objeto. Ver: javascript.crockford.com/code.html
    • Como se ha comentado en otra respuesta(s), el «por » en» no funciona correctamente para las Matrices, como se va a iterar sobre todos los de la Matriz de propiedades y métodos. Por lo tanto, usted debe usar «por » en» sólo para iterar sobre las propiedades del objeto. De lo contrario, se adhieren a «for(i=0; i<algo; i++)»
    • Por motivos de rendimiento, la OMI es mejor para evaluar la longitud de la matriz antes de la for, no evaluar.la longitud de cada vez en el bucle.
    • Que es sin duda cierto cuando la matriz es de hecho algo devuelto por el HTMLDOM, sin embargo, me pregunto qué tan grande de un estándar array de javascript tendría que ser antes de que usted podría ver una diferencia apreciable? Personalmente me quedaría con el código tan simple como sea posible hasta que su probada necesario para hacer algo diferente.
    • En algún momento, empecé a usar for (var i = 0, l = a.length; i < a; i++) {} y se pegó con él. Es un poco más complejo que el i < a.length y su efecto en el rendimiento en la mayoría de los casos no vale la pena mencionar, pero se hace más fácil para el tipo de cada vez y por lo menos yo lo considero como un «limpiador» método, porque.la longitud no tiene que ser evaluado en cada momento. Puedo decir que soy feliz con mi cambio de MooTools una.cada(…).
    • Creo que te refieres i < l, no i < a, en su condición de bucle.
    • Sí, tanto para la «más fácil escribir cada vez» 😀
    • for (var i = 0; i < a.longitud; i++) método no puede ser utilizado para una matriz dispersa como cuando usted hace; myArray[110]=»foo»; myArray[180]=»fie»;
    • Usted debe obtener la longitud de la matriz antes de la for bucle porque de lo contrario el .length obtendrá evaluados en cada iteración del bucle.
    • Acabo de encontrar un interesante fallo. for ... in statement se elenco entero en una cadena cuando se itera un array de enteros.

  2. 160

    Douglas Crockford recomienda en JavaScript: Las Partes Buenas (página 24) para evitar el uso de la for in declaración.

    Si utiliza for in para recorrer los nombres de propiedad en un objeto, los resultados no están ordenadas. Peor: puede obtener resultados inesperados; incluye a los miembros heredados de la cadena de prototipos y el nombre de los métodos.

    Todo, pero las propiedades pueden ser filtrados con .hasOwnProperty. Este ejemplo de código hace lo que probablemente quería originalmente:

    for (var name in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, name)) {
            //DO STUFF
        }
    }
    • Segundo, que – foreach… no está haciendo lo que se podría esperar (esp si viene de .net) y probablemente no sea lo que estás tratando de hacer.
    • para…en es perfectamente adecuada para recorrer las propiedades del objeto. No es apropiado para recorrer los elementos de una matriz. Si usted no puede entender la diferencia entre estos escenarios, entonces sí, usted debe evitar, por…en; de lo contrario, se vuelven locos.
    • Quiero enfatizar el hecho de que NO es ORDENADO! Esto podría ser un gran problema, y sería un error difícil de atrapar.
    • En teoría no es ordenado, pero en todos los navegadores modernos, es (excepto en los raros casos en Chrome, al parecer). Creo que el futuro JavaScripts tendrá un orden garantizado.
    • +1 para «incluye a los miembros heredados de la cadena de prototipos y el nombre de los métodos.» Te vas a divertir si a alguien le sucede al utilizar el código con el Prototipo de la carga (incluso si el código no lo uso), por ejemplo.
    • Por favor, no te olvides de declarar el name variable: for(var name in object)..., de lo contrario, si ese código dentro de una función, por ejemplo, la name variable terminan siendo una propiedad del objeto global (una asignación a un identificador no declarado hace eso), también en el nuevo ECMAScript 5 Modo Estricto, que el código que se va a lanzar una ReferenceError.
    • También ten en cuenta que si se itera sobre una Clase en la que va a conseguir es que los niños, incluyendo todos sus definido por el usuario prototipos, etc. Esto no es muy eficiente, incluso si utiliza hasOwnProperty() y otro escenario para seguir con una simple instrucción for. Como se menciona sólo a ir cerca para que en las declaraciones cuando se tienen las Matrices Asociativas
    • Hay una cuestión acerca de la orden de iteración para Chrome, presentada nada menos que por John Resig, que está marcado como WontFix. code.google.com/p/chromium/issues/detail?id=883 . Incluso antes de que chrome, el orden de iteración no fue el mismo en todos los navegadores si quitar y, a continuación, agregar una propiedad de nuevo. También IE 9 se comporta mucho como chrome (supuestamente para mejoras en la velocidad). Así que… por Favor, dejar de difundir información inexacta, tendría que ser muy ingenuo para mantener dependen de ella.
    • Consulte la sección «Comentarios» debajo de msdn.microsoft.com/en-us/library/55wb2d34(v=vs 94).aspx.
    • Si una vez que usted va a hacer la refactorización de la matriz a objeto de que se rehúsen a partir de for (var i = 0; i < a.longitud; i++)

  3. 62

    FYI – jQuery los Usuarios


    jQuery each(callback) método utiliza for( ; ; ) bucle por defecto, y el uso de for( in ) sólo si la longitud es undefined.

    Por lo tanto, yo diría que es seguro asumir que el orden correcto cuando se utiliza esta función.

    Ejemplo:

    $(['a','b','c']).each(function() {
        alert(this);
    });
    //Outputs "a" then "b" then "c"

    La desventaja de utilizar este método es que si usted está haciendo algunos no lógica de interfaz de usuario, sus funciones serán menos portable a otros marcos. El each() función es probablemente el mejor reservado para el uso con los selectores de jQuery y for( ; ; ) podría ser aconsejable en caso contrario.


    • Siempre hay documentcloud.github.com/underscore que tiene _.cada uno y un montón de otras funciones útiles
    • también decir que si tengo la longitud de la propiedad en mi objeto $.cada uno va a fallar? por ejemplo, x= { a:»1″, b:»2″, longitud:3 }.
  4. 29

    hay diferencias de rendimiento en función de qué tipo de bucle utiliza y en qué navegador.

    Por ejemplo:

    for (var i = myArray.length-1; i >= 0; i--)

    es casi dos veces más rápido en algunos navegadores que:

    for (var i = 0; i < myArray.length; i++)

    Sin embargo, a menos que las matrices son ENORMES o bucle de ellos constantemente están lo suficientemente rápido. Tengo serias dudas de que la matriz de bucle es un cuello de botella en su proyecto (o para cualquier otro proyecto, para el caso)

    • Sería almacenar «myArray.longitud» en una variable antes de bucle de hacer la diferencia de rendimiento se vaya? Mi conjetura es «sí».
    • Tendría al menos la mayoría de desaparecer. Sin embargo, si no recuerdo mal yo– es ligeramente más rápido que i++. En cualquier caso las diferencias son muy pequeñas.
    • Pero todavía estamos hablando de JavaScript aquí, no ensamblador, ¿no? 🙂
    • No estoy seguro de que ya 😀 sé que era, pero no saben acerca de usted
    • ‘.’ es bastante terriblemente mal desempeño en JS (o, al menos, IE7 JS), en mi experiencia, vale la pena fuerza-reducción, como aquí.
    • No’. myArray.longitud’ es una propiedad, no es un método en un objeto, no hay un cálculo que se realiza para determinar su valor. Almacenar su valor en una variable no hará nada en absoluto.
    • Sí que la hay. Las propiedades no son variables, tienen get/set código.
    • Yo tiendo a usar for(var i = myArray.length; i--;)
    • La forma más rápida es utilizar un bucle while: var l = myArray.length; while (i--) { }
    • buena convocatoria, pero de asignar longitud de l y disminuir i – hay que escoger uno. Este es también equivalente a for(var i = myArray.length - 1; i--; ) { }.
    • He probado que for(var i=0,n=myArray.longitud;i<n;i+=1) es más rápido que utilizar i++ (en Firefox).
    • Históricamente, a la inversa, mientras que era el rey: var L=arr.length; while(L--){}. Entonces (alrededor de FF 3.5 época) for era mejor optimizado (probablemente porque era el más utilizado, especialmente por ‘script kiddy’ código). En esa época, la inversa for era el rey: for(var L=arr.length; L--;){}. A continuación, recientemente optimizaciones se convirtió en mucho más inteligente y por fin pudimos empezar a notar de Caché de CPU-se pierde. Fragmentar en partes de (por ejemplo) int-matrices se requiere para todos los pequeños/inverso del índice, mientras que en adelante se utiliza la caché, como se pretendía. Porque for es aún más rápido, ahora la regular hacia delante-loop es a menudo el rey.
    • Código para la claridad y la legibilidad. No por lo que sucede a correr un poco más rápido en algunos navegadores cuando se utiliza absurdamente enorme matrices en el momento actual en el tiempo. Optimizaciones pueden cambiar, pero el código de la legibilidad (o falta de ella) no. Escribir código que otros pueden seguir fácilmente, y dejar que los optimizadores de la pelota en su propio y debido tiempo.

  5. 26

    Tenga en cuenta que la Matriz nativa.método forEach es ahora ampliamente soportado.

    • ¿Qué hacer? No se tienen los problemas que he mencionado en otros posts (en un bucle sobre propiedades en lugar de los elementos de la matriz)? También, como IE8 no lo soporta, que es un poco de un tramo a decir que es ampliamente apoyado.
    • tanto como *nix usuarios desprecio, IE8 es que la mayoría de todos los sub-windows7 los usuarios. eso es una enorme porción del mercado de los navegadores.
    • Puedo tomar su punto, pero para dispositivos de escritorio del navegador IE compartir es menor de 40%, según en.wikipedia.org/wiki/Usage_share_of_web_browsers#Summary_table, y de acuerdo a la marketshare.hitslink.com/… y otros sitios, al menos el 8% de los navegadores están IE 9. En otras palabras, la Matriz.forEach es apoyada por alrededor de 70% de los navegadores de escritorio, así que no creo que ‘ampliamente apoyado’ no es razonable. No he comprobado, pero el soporte móvil (en WebKit y Opera navegadores) puede ser aún mayor. Obviamente, hay considerables variaciones geográficamente.
    • Gracias por la actualización. Estoy de acuerdo en que se podría decir que es «ampliamente apoyado». El único problema es que si el usuario utiliza este JS método, Él/Ella todavía tiene que escribir un método de respaldo para el caso si no es compatible..
    • usted puede utilizar es5-shim y es6-calza para proporcionar de forma automática una copia de seguridad de los métodos. github.com/es-shims/es5-shim
    • La mayoría de estimación generosa para las personas que siguen usando IE 7 o más en el que puedo encontrar en el 2015 es del 15%, a partir de NetApplications. La mayoría de las otras fuentes de lista es de 3% o menos trivial suficiente que creo que se puede prescindir de las mismas.

  6. 24

    Respuesta actualizada para el año 2012 versión actual de todos los principales navegadores: Chrome, Firefox, IE9, Safari y Opera apoyo ES5 nativas de la matriz.forEach.

    Menos que haya alguna razón para apoyar IE8 de forma nativa (teniendo en cuenta ES5-shim o Chrome frame puede ser proporcionada a estos usuarios, que proporcionan una adecuada JS medio ambiente), es más, simplemente, el uso del lenguaje de la sintaxis correcta:

    myArray.forEach(function(item, index) {
        console.log(item, index);
    });

    Documentación completa para la matriz.forEach() es en MDN.

    • Usted realmente debe documentar la devolución de llamada a los parámetros de: 1º el valor del elemento, 2º el índice del elemento, 3 de la matriz que se recorre
    • Puedo oír lo que estás diciendo, pero en este caso simplificando oculta la gama completa de posibilidades. Tener tanto el índice y el valor medio que puede servir como un reemplazo para para…en y para cada…en con el bono que usted no tiene que recordar que itera a través de claves o valores.
    • Hay un montón de personas en entornos corporativos, que todavía está atascado en IE 6, 7 y 8. Definitivamente, me gustaría asegurarse de que su elección de la aplicación apropiada para su público.
    • ES5 forEach puede ser añadido a la herencia ES3 navegadores con bastante facilidad. Menos código es un código mejor.
    • Puede ser usado en los arrays y objetos indistintamente?
    • Es parte de la Matriz de prototipo, no del Objeto. En general, en el derecho de la comunidad ahora no objetos de la Matriz son todavía afirmar con ‘for ( var clave en el objeto ) {}’.

  7. 14

    Usando forEach para saltarse la cadena de prototipos

    Sólo una rápida adición a @clavador de la respuesta de arriba, usando forEach con el Objeto.teclas significa que usted puede evitar la iteración sobre el prototipo de la cadena sin tener que utilizar hasOwnProperty.

    var Base = function () {
        this.coming = "hey";
    };
    
    var Sub = function () {
        this.leaving = "bye";
    };
    
    Sub.prototype = new Base();
    var tst = new Sub();
    
    for (var i in tst) {
        console.log(tst.hasOwnProperty(i) + i + tst[i]);
    }
    
    Object.keys(tst).forEach(function (val) {
        console.log(val + tst[val]);
    });
    • maldita sea, eso es astuto. Valió la pena la lectura de otros 50 post para llegar a esto. obj={«color de rosa»:»los patos», en rojo: «gansos»}; Objeto.claves(obj) === [«color de rosa», «red»]
  8. 14

    Me segundas opiniones que usted debe elegir el método de iteración de acuerdo a su necesidad. Yo sugiero que en realidad no nunca bucle a través de los nativos Array con for in estructura. Es la manera más lento y, como Chase Seibert, señaló en el momento en que hace, no es compatible con el Prototipo de marco.

    Hay un excelente punto de referencia en bucle diferente estilos que usted absolutamente debe echar un vistazo en el caso de trabajar con JavaScript. No hacer optimizaciones, pero debe mantener las cosas en algún lugar en la parte de atrás de su cabeza.

    Me gustaría utilizar for in para obtener todas las propiedades de un objeto, que es especialmente útil cuando la depuración de los scripts. Por ejemplo, me gustaría tener esta línea de la mano cuando voy a explorar objeto desconocido:

    l = ''; for (m in obj) { l += m + ' => ' + obj[m] + '\n' } console.log(l);

    Se vuelca el contenido de todo el objeto (junto con el método de los órganos) a mi Firebug de registro. Muy mano.

    • Buen punto de referencia en el enlace.
    • El enlace está roto ahora. Seguro que le gustaría ver en el punto de referencia, si alguien tiene otro enlace.
    • No esta roto ya.
    • Los bucles Foreach interrupción en el prototipo? Como lo es ahora comúnmente admitidos, que es algo prototipo se debe resolver.
  9. 13

    Los dos no son la misma cuando la matriz es dispersa.

    var array = [0, 1, 2, , , 5];
    
    for (var k in array) {
      //Not guaranteed by the language spec to iterate in order.
      alert(k);  //Outputs 0, 1, 2, 5.
      //Behavior when loop body adds to the array is unclear.
    }
    
    for (var i = 0; i < array.length; ++i) {
      //Iterates in order.
      //i is a number, not a string.
      alert(i);  //Outputs 0, 1, 2, 3, 4, 5
      //Behavior when loop body modifies array is clearer.
    }
  10. 7

    aquí es algo que yo hice.

    function foreach(o, f) {
     for(var i = 0; i < o.length; i++) { //simple for loop
      f(o[i], i); //execute a function and make the obj, objIndex available
     }
    }

    esta es la manera de usarlo

    esto funcionará en los arrays y objetos( como una lista de elementos HTML )

    foreach(o, function(obj, i) { //for each obj in o
      alert(obj); //obj
      alert(i); //obj index
      /*
        say if you were dealing with an html element may be you have a collection of divs
      */
      if(typeof obj == 'object') { 
       obj.style.marginLeft = '20px';
      }
    });

    Acabo de hacer esto, así que estoy abierto a sugerencias 🙂

    • Grandes cosas – bastante straightforwards!
  11. 6

    Que haría uso de los diferentes métodos basados en la manera en que yo quise hacer referencia a los elementos.

    Usar foreach si sólo quieres el elemento actual.

    Uso si usted necesita un indizador para hacer comparaciones relativas. (I. e. cómo se compara esto con el elemento anterior/siguiente?)

    Nunca he notado una diferencia de rendimiento. Me gustaría esperar hasta tener un problema de rendimiento antes de que preocuparse.

    • Ver Bnos respuesta a continuación – para…no es hacer lo que te espera aquí y si usted lo usa usted puede tener todo tipo de diversión. Para el registro, Prototipo hace las cosas de la derecho camino.
  12. 4

    Con for (var i en myArray) puede crear un bucle a través de objetos, me contendrá el nombre de la clave y se puede acceder a la propiedad a través de myArray[i]. Además, los métodos que se han añadido al objeto será incluido en el bucle, demasiado, es decir, si usted utiliza cualquier servicio externo de framework como jQuery o prototype, o si usted añadir métodos a objeto de prototipos directamente, en un punto me apuntará a esos métodos.

  13. 4

    ¡Cuidado!

    Si usted tiene varias etiquetas de secuencia de comandos y tu eres la búsqueda de información en la etiqueta de los atributos por ejemplo, usted tiene que utilizar .propiedad de longitud con un bucle for, ya que no es un simple array, pero un HTMLCollection objeto.

    https://developer.mozilla.org/en/DOM/HTMLCollection

    Si utiliza la instrucción foreach for(var i en yourList) devolverá proterties y métodos de la HTMLCollection en la mayoría de los navegadores!

    var scriptTags = document.getElementsByTagName("script");
    
    for(var i = 0; i < scriptTags.length; i++)
    alert(i); //Will print all your elements index (you can get src attribute value using scriptTags[i].attributes[0].value)
    
    for(var i in scriptTags)
    alert(i); //Will print "length", "item" and "namedItem" in addition to your elements!

    Incluso si getElementsByTagName debe devolver una lista de nodos, la mayoría de los navegadores están volviendo un HTMLCollection:
    https://developer.mozilla.org/en/DOM/document.getElementsByTagName

  14. 3

    Para en bucles sobre Matrices no es compatible con el Prototipo. Si usted piensa que usted podría necesitar el uso de la biblioteca en el futuro, tendría sentido seguir para bucles for.

    http://www.prototypejs.org/api/array

    • Olvidar «usted podría necesitar el uso de la biblioteca». Creo que en lugar de «tu JS pueden ser incluidos con otra cosa que utiliza la biblioteca», porque los problemas siguen llegando.
  15. 3

    He visto problemas con el «para cada» uso de objetos y el prototipo y matrices

    mi entendimiento es que el uno es para las propiedades de los objetos y NO de las matrices de

  16. 3

    Si usted realmente desea acelerar su código, ¿qué es eso?

    for( var i=0,j=null; j=array[i++]; foo(j) );

    es un poco de tener el tiempo dentro de la lógica de la instrucción for y es menos redundante. También firefox ha Matriz.forEach y de la Matriz.filtro de

    • ¿Por qué esta velocidad de tu código? No veo por qué reording declaraciones como esta podría acelerar.
  17. 3

    Más corto y mejor código de acuerdo a jsperf es

    keys  = Object.keys(obj);
    for (var i = keys.length; i--;){
       value = obj[keys[i]];//or other action
    }
  18. 1

    El uso de la Matriz().bucle forEach para aprovechar las ventajas del paralelismo

    • JavaScript en el navegador es el bucle de eventos simultáneos para Array.prototype.forEach no ejecutar varias llamadas a la devolución de llamada en paralelo.
  19. 0

    Cuidado!!!
    Estoy usando Chrome 22.0 en Mac OS y estoy teniendo problemas con la sintaxis.

    No sé si esto es un problema del navegador, javascript problema o algún error en el código, pero es MUY extraño. Fuera del objeto que funciona a la perfección.

    var MyTest = {
        a:string = "a",
        b:string = "b"
    };
    
    myfunction = function(dicts) {
        for (var dict in dicts) {
            alert(dict);
            alert(typeof dict); //print 'string' (incorrect)
        }
    
        for (var i = 0; i < dicts.length; i++) {
            alert(dicts[i]);
            alert(typeof dicts[i]); //print 'object' (correct, it must be {abc: "xyz"})
        }
    };
    
    MyObj = function() {
        this.aaa = function() {
            myfunction([MyTest]);
        };
    };
    new MyObj().aaa(); //This does not work
    
    myfunction([MyTest]); //This works
  20. 0

    Hay una diferencia importante entre ambos. El para-en itera a través de las propiedades de un objeto, de modo que cuando el caso es una matriz no sólo va a iterar a través de sus elementos, sino también a través de la opción de «eliminar» la función que tiene.

    for (var i = 0; i < myArray.length; i++) { 
        console.log(i) 
    }
    
    //Output
    0
    1
    
    for (var i in myArray) { 
        console.log(i) 
    } 
    
    //Output
    0 
    1 
    remove

    Usted podría utilizar el para-con un if(myArray.hasOwnProperty(i)). Aún así, cuando se itera a través de matrices yo siempre prefiero evitar esto y sólo tiene que utilizar el for(;;) declaración.

  21. 0

    A pesar de que ambos son muy parecidos, existe una pequeña diferencia :

    var array = ["a", "b", "c"];
    array["abc"] = 123;
    console.log("Standard for loop:");
    for (var index = 0; index < array.length; index++)
    {
      console.log(" array[" + index + "] = " + array[index]); //Standard for loop
    }

    en este caso, la salida es :

    ESTÁNDAR BUCLE FOR:

    MATRIZ[0] = A

    ARRAY[1] = B

    ARRAY[2] = C

    console.log("For-in loop:");
    for (var key in array)
    {
      console.log(" array[" + key + "] = " + array[key]); //For-in loop output
    }

    mientras que en este caso, la salida es:

    PARA-EN EL BUCLE:

    ARRAY[1] = B

    ARRAY[2] = C

    MATRIZ[10] = D

    MATRIZ[ABC] = 123

  22. 0

    La para en la declaración permite bucle a través de los nombres de todas las propiedades de un objeto. Por desgracia, también recorre todos los miembros que fueron heredados a través de la cadena de prototipos. Esto tiene el efecto malo del lado de los que sirven funciones de método, cuando el interés está en los miembros de datos.

Dejar respuesta

Please enter your comment!
Please enter your name here