Pregunta Loop a través de una matriz en JavaScript


En Java puedes usar un for bucle para recorrer objetos en una matriz de la siguiente manera:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

¿Puedes hacer lo mismo en JavaScript?


2415
2018-06-10 00:04


origen


Respuestas:


Use una secuencia for lazo:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    alert(myStringArray[i]);
    //Do something
}

@zipcodeman sugiere el uso de for...in declaración, pero para iterar matrices for-in debe evitarse, esa declaración está destinada a enumerar propiedades del objeto.

No debería usarse para objetos tipo array porque:

  • El orden de iteración no está garantizado, los índices de matriz no se pueden visitar en orden numérico.
  • Las propiedades heredadas también se enumeran.

El segundo punto es que puede darte muchos problemas, por ejemplo, si extiendes el Array.prototype objeto para incluir un método allí, esa propiedad también será enumerada.

Por ejemplo:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
  alert(array[i]);
}

El código anterior alertará, "a", "b", "c" y "foo!".

Eso será particularmente un problema si utiliza alguna biblioteca que dependa en gran medida del aumento de prototipos nativos (como MooTools, por ejemplo).

los for-in declaración, como dije antes, está ahí para enumerar propiedades del objeto, por ejemplo:

var obj = {
  "a": 1,
  "b": 2,
  "c": 3
};

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) { 
  // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

En el ejemplo anterior, hasOwnProperty método le permite enumerar solo propiedades propias, eso es todo, solo las propiedades que el objeto tiene físicamente, sin propiedades heredadas.

Te recomendaría que leyeras el siguiente artículo:


3050
2018-06-10 00:07



Sí, pero solo si su implementación incluye el for...of característica introducida en ECMAScript 2015 (la versión de "Harmony").

Funciona así:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

O mejor aún, ya que ECMAScript 2015 también proporciona variables de ámbito de bloque a través de let y const:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

Sin embargo, muchos desarrolladores de JavaScript siguen trabajando en un entorno que todavía no existe, especialmente si se trata de escribir código para ejecutar en navegadores web, donde los desarrolladores de sitios a menudo no pueden estar seguros de qué navegador / versión usarán sus clientes.

Si puede asumir que el intérprete de JavaScript es compatible con el anterior edición de la especificación ECMAScript (que descarta, por ejemplo, las versiones de Internet Explorer antes de 9), entonces puede usar el forEach método iterador en lugar de un bucle. En ese caso, pasa una función para llamar a cada elemento en la matriz:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

Pero si incluso eso es demasiado para suponer, y quieres algo que funcione en todas versiones de JavaScript, entonces tiene que usar un ciclo de conteo explícito. La versión más segura, que maneja las matrices dispersas correctamente, es algo como esto:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Asignación del valor de longitud a la variable local (en lugar de incluir el valor completo) myStringArray.length expresión en la condición de bucle) puede hacer una diferencia significativa en el rendimiento, ya que omite una búsqueda de propiedad cada vez que pasa; usando Rhino en mi máquina, la aceleración es 43%.

A menudo verá el caché de longitud hecho en la cláusula de inicialización de bucle, como este:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

los for...in la sintaxis mencionada por otros es para recorrer las propiedades de un objeto; ya que una matriz en JavaScript es solo un objeto con nombres de propiedades numéricas (y una actualización automática) lengthpropiedad), teóricamente puedes recorrer una Array con ella. Pero el problema es que no se restringe a los valores de propiedad numéricos (recuerde que incluso los métodos son en realidad solo propiedades cuyo valor es un cierre), ni itera sobre aquellos en orden numérico. Por lo tanto, la for...in la sintaxis debería no ser utilizado para bucles a través de matrices.


868
2018-04-16 02:03



Puedes usar map, que es una técnica de programación funcional que también está disponible en otros idiomas, como Pitón y Haskell.

[1,2,3,4].map( function(item) {
     alert(item);
})

La sintaxis general es:

array.map(func)

En general func tomaría un parámetro, que es un elemento de la matriz. Pero en el caso de JavaScript, puede tomar un segundo parámetro, que es el índice del elemento, y un tercer parámetro, que es la matriz misma.

El valor de retorno de array.map es otra matriz, por lo que puedes usarla así:

var x = [1,2,3,4].map( function(item) {return item * 10;});

Y ahora es x [10,20,30,40].

No tiene que escribir la función en línea. Podría ser una función separada.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

que sería una especie de equivalente a:

 for (item in my_list) {item_processor(item);}

Excepto que no obtienes el new_list.


391
2018-06-10 00:09



En JavaScript, no es recomendable recorrer una matriz con un bucle for-in, pero es mejor usar un bucle for, como:

for(var i=0, len=myArray.length; i < len; i++){}

También está optimizado ("almacenamiento en caché" de la longitud de la matriz). Si desea obtener más información, lee mi publicación sobre el tema.


102
2017-12-07 07:24



for (var s of myStringArray) {

(Respondiendo directamente a su pregunta: ¡ahora puede!)

La mayoría de las otras respuestas son correctas, pero no mencionan (al momento de escribir esto) que ECMA Script 6 2015 está trayendo un nuevo mecanismo para hacer la iteración, el for..of lazo.

Esta nueva sintaxis es la manera más elegante de iterar una matriz en javascript (siempre que no necesite el índice de iteración), pero los navegadores aún no la admiten ampliamente.

Actualmente funciona con Firefox 13+, Chrome 37+ y no funciona de forma nativa con otros navegadores (consulte la compatibilidad del navegador a continuación). Afortunadamente tenemos compiladores JS (como Babel) que nos permiten usar las funciones de próxima generación hoy.

También funciona en Node (lo probé en la versión 0.12.0).

Iterar una matriz

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Iterando una matriz de objetos

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Iterar un generador:

(ejemplo extraído de https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Tabla de compatibilidad: http://kangax.github.io/es5-compat-table/es6/#For..of loops

Especulación:  http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}


92
2017-08-11 15:54



Opera, Safari, Firefox y Chrome ahora comparten un conjunto de métodos Array mejorados para optimizar muchos bucles comunes.

Puede que no los necesite todos, pero pueden ser muy útiles, o lo serían si cada navegador los admitiera.

Mozilla Labs publicó los algoritmos que ellos y WebKit ambos usan, para que pueda agregarlos usted mismo.

filtrar devuelve una matriz de elementos que satisfacen alguna condición o prueba.

cada devuelve verdadero si cada miembro de la matriz pasa la prueba.

algunos devuelve verdadero si alguno pasa la prueba.

para cada ejecuta una función en cada miembro de la matriz y no devuelve nada.

mapa es como paraCada, pero devuelve una matriz de los resultados de la operación para cada elemento.

Todos estos métodos toman una función para su primer argumento y tienen un segundo argumento opcional, que es un objeto cuyo alcance desea imponer a los miembros de la matriz a medida que recorren la función.

Ignore hasta que lo necesite.

índice de y lastIndexOf encuentre la posición apropiada del primer o último elemento que coincida exactamente con su argumento.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();

81
2018-06-10 02:43



Usa el ciclo while ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

registros: 'uno', 'dos', 'tres'

Y para el orden inverso, un bucle aún más eficiente

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

registros: 'tres', 'dos', 'uno'

O el clásico for lazo

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

registros: 'uno', 'dos', 'tres'

Referencia: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


62
2018-01-05 09:15