17

Buen consejo para iterar arreglos en JavaScript

30Oct
en Javascript, Tutoriales, Web

Uno de los tips más recomendados para optimizar tu código JavaScripts recomienda chachear las longitudes de los arreglos (Arrays) a la hora de iterarlos.

Normalmente la manera más común de iterar sobre un arreglo es la siguiente:

var arr = [ 'a', 'b', 'c' ] ;
for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]);
};

Ejemplo 1

El referido tips consiste en almacenar la longitud del arreglo en una variable antes de recorrerlo, con el objetivo de no tener que recalcular dicha longitud en cada iteración. Esto se haría de la siguiente manera:

var arr = ['a', 'b', 'c'] ;
for (var i = 0, long = arr.length; i < long; i++) {
    console.log(arr[i]);
};

Ejemplo 2

Pero bien. ¿Realmente este tips es necesario? ¿Se recalcula la longitud del arreglo en cada iteración?

Ya han de suponer que las respuestas para estas dos preguntas son no. Claramente, y explico por qué.

La longitud en los arreglos de JavaScripts nos es más que una propiedad (length) que se actualiza al insertar o extraer elementos del arreglo. Esto permite que se pueda acceder a ella directamente de igual manera que como se hace con las propiedades de los objetos, puesto que en JavaScripts los arreglos son objetos. La complejidad de acceder a cualquier propiedad de un objeto es la misma que la de acceder a una variable (Complejidad temporal lineal O(1)). Por lo tanto, la forma tradicional de iterar los arreglos (ejemplo 1) no tiene ningún inconveniente según lo planteado, dejando la recomendación del ejemplo 2 sin validez.

Para finalizar acá les dejo con una de las funciones de los arreglos, muy útil para recorrerlos “de punta a cabo”. En el próximo post escribiré algunas cosas más sobre los arreglos en JavaScripts y su propiedad length.

['a', 'b', 'c'].forEach(
    function (elem, index) {
        console.log('En la posición: ' + index + ' se encuentra el elemento: ' + elem);
});

 

Etiquetado en:

17 Comentarios

  1. Yosbel Marin dice:

    @Julio Cesar, La recomendación del ejemplo 2 tiene mucha validez. Los objetos guardan sus propiedades mediante una tabla hash. El acceso a una tabla hash es O(1) pero requiere un calculo (Ojo con esto, para encontrar el indice en la tabla) de todas maneras y ese calculo para leer el valor de “length” es ejecutado N veces, mientras que cacheando “length” el calculo se realiza una vez.

    En fin, ambas complejidades son O(1) pero el ejemplo 2 tiene mayor rendimiento.

    Saludos.

    • Julio Cesar dice:

      Gracias por tu comentario. Dejar claro que leer un valor de una variable o de una propiedad de un objeto es de complejidad temporal O(1), ambas se gestionan de igual modo por el lenguaje. Cuando se cachea el valor del “length” como en el ejemplo 2, durante la iteración del arreglo este valor no es actualizado si se modifica la longitud, pues como decís este es leído una sola vez, lo que puede ser ventajoso en determinados casos.

      • Yosbel Marin dice:

        Haz una prueba de rendimiento y veras la diferencia, en caso que dentro del ciclo se modifiquen los items del arreglo la primera opción es la indicada pero en caso contrario (que es la gran mayoría de los casos) el segundo ofrece mejor rendimiento.

  2. GUstavo dice:

    for (var i in data.list_users) {
    console.log(‘En la posición: ‘ + i + ‘ se encuentra el elemento: ‘ + data.list_users[i]);
    }

  3. Josh dice:

    Pues bueno, acá le comparto mis experiencias con unos ejemplos, asumiendo que todos usamos Firebug, solo peguen el código que les comparto a cotinuación en la consola de dicha herramienta.

    //Inicialmente creamos un Super-Array :)
    var array = [];
    for (var i=0;i<=500000;i++){
    array[i]=i;
    }

    //Medimos el Tiempo de la Propuesta 1
    var inicio = +new Date();
    for (var i=0;i<= array.length;i++){
    array[i];
    }
    console.log("Duración: " + (+new Date() - inicio) + "ms");

    //Medimos el Tiempo de la Propuesta 2
    inicio = +new Date();
    var length = array.length;
    for (var i=0;i<= length;i++){
    array[i];
    }
    console.log("Duración: " + (+new Date() - inicio) + "ms");

    //Y esta la que mejores resultados me ha dado
    inicio = +new Date();
    var length = array.length;
    for (var i=0;i<= length;i+=1){
    array[i];
    }
    console.log("Duración: " + (+new Date() - inicio) + "ms");

    //Esta es la menos eficiente de todas
    inicio = +new Date();
    for (var i in array) {
    array[i];
    }
    console.log("Duración: "+ (+new Date() - inicio) + "ms");

    Saludos!

    • Josh dice:

      Al final el mejor consejo para iterar es utilizar:
      i+=1 en vez de i++

    • Yosbel Marin dice:

      Segun mi experiencia esta es la manera mas rapidas de iterar arrays y es la que uso, no he encontrado otra mas rapida:

      var length = array.length, i = 0;
      while (++i <= length){
      array[i];
      }

      • Julio Cesar dice:

        Estimado, sin dudas recorrer un array de la manera que dices es la más rápida, mi experiencia coincide. Pero el ejemplo que pones tiene unos pequeños problemitas: No tiene en cuenta la posición inicial del arreglo (array[0]), pues ++i incrementa i y luego opera con su valor.Además evalúa el array una posición fuera del rango por poner “<= length". De esta manera resulta mejor:

        var long = array.length, i = 0;
        while (i < long){
        array[i++];
        }

        • Yosbel Marin dice:

          Oops! mala mia, el snipet fue escrito burdamente para usarlo con la prueba de rendimiento propuesta anteriormente por @Josh.

          Pero en un caso practico seria:

          var length = array.length, i = -1;
          while (++i < length){
          array[i];
          }

    • kceres dice:

      bueno, mis tiempos fueron esto:

      Duración: 724ms
      Duración: 695ms
      Duración: 689ms
      Duración: 555ms

      en teoría la última que dices que es la menos eficiente es la que menos tiempo consume

      • Josh dice:

        Bueno, algo de razón llevas:
        En Chrome 37 los resultados coinciden con lo que planteas.

        Duración: 490ms
        Duración: 455ms
        Duración: 453ms
        Duración: 373ms

        Firefox 31:

        Duración: 224ms
        Duración: 216ms
        Duración: 200ms
        Duración: 344ms

        Internet Explorer 10:

        Duración: 85ms
        Duración: 76ms
        Duración: 75ms
        Duración: 152ms

  4. krlos dice:

    HOlaaaa. Quiero aprender a desarrollar addons para firefox pero no se por donde empezar y no veo en el sitio bibliografia y herramientas. Alguien me puede ayudar??

  5. Otra forma que les aconsejo es:

    var arr = [ ‘a’, ‘b’, ‘c’ ];
    for(arr in a){
    console.log(a);
    }

    Como pueden ver es mas intuitivo y elegante.
    Salu2s.

  6. Yunier J dice:

    En ES6 han introducido iteradores y for-of, en el caso de for-of aconsejan su uso sobre forEach pues se pueden interrumpir el ciclo, retornar valores y continuar.

    for (var value of myArray) {
    console.log(value);
    }

    Si desean saber mas pueden visitar Mozilla Hacks https://hacks.mozilla.org/2015/04/es6-in-depth-iterators-and-the-for-of-loop/

  7. Ernesto dice:

    Alguien me puede proporcionar algo de documentación para iniciarme en la programación de plugins para firefox, la verdad estuve buscando un poco y no encontré algo que me inicie, es decir que me explique como es la estructura, donde va cada cosa y demas.. Saludos y Gracias de antemano.

    PD: Mi email no se si lo pueda poner aquí, de todos modos lo hago para que me puedan contactar:

Dejar un comentario

¿Eres humano? Entonces resuelve esta operación: * Límite de tiempo se agote. Por favor, recargar el CAPTCHA por favor.