Contactos

Iterando sobre propiedades en objetos. JQuery: recorrido por matrices, objetos y elementos explícitamente utilizando el iterador

Funciona así:

// REQUIERE ECMASCRIPT 2015+ var s, myStringArray = ["Hola", "Mundo"]; for (s of myStringArray) ( // ... hacer algo con s ... )

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

// REQUIERE ECMASCRIPT 2015+ const myStringArray = ["Hola", "Mundo"]; for (const s of myStringArray) ( // ... hacer algo con s ... ) // s ya no está definido aquí

Una nota sobre las matrices dispersas: es posible que una matriz en JavaScript no almacene tantos elementos como se especifica en su longitud; este número informado es simplemente uno mayor que el índice más alto en el que se almacena el valor. Si una matriz contiene menos elementos de los que indica su longitud, se dice que es escasa. Por ejemplo, es perfectamente legal tener una matriz con elementos sólo en los índices 3, 12 y 247; La longitud de dicha matriz se especifica como 248, aunque en realidad solo almacena 3 valores. Si intenta acceder al elemento en cualquier otro índice, la matriz tendrá un valor indefinido. Entonces, cuando desea "iterar" una matriz, tiene una pregunta que debe responderse: ¿desea iterar sobre todo el rango especificado por su longitud y procesar indefinido para cualquier elemento faltante, o desea procesar solo el elementos realmente presentes? Hay muchas aplicaciones para ambos enfoques; solo depende de para qué estés usando la matriz.

Si iteras sobre una matriz con for .. of , el cuerpo del bucle se ejecuta por longitud y la variable de control del bucle se establece en indefinido para cualquier elemento que no esté realmente en la matriz. Dependiendo de los detalles de su código "hacer algo", este comportamiento puede ser lo que desea, pero si no es lo que desea, debe utilizar un enfoque diferente.

Por supuesto, algunos desarrolladores no tienen más remedio que utilizar un enfoque diferente de todos modos, porque por alguna razón están apuntando a una versión de JavaScript que aún no es compatible con... de .

Siempre que su implementación de JavaScript sea compatible con una versión anterior de la especificación ECMAScript (que, por ejemplo, excluye las versiones de Internet Explorer anteriores a la 9), puede utilizar el método iterador Array#forEach en lugar de un bucle. En este caso, pasas una función que se llamará para cada elemento de la matriz:

Var myStringArray = [ "Hola", "Mundo" ]; myStringArray.forEach(function(s) ( // ... hacer algo con s ... ));

A diferencia de for ... of , .forEach solo llama a la función en elementos que realmente contienen valores. Si pasamos nuestra matriz hipotética con tres elementos y una longitud de 248, solo llamará a la función tres veces, no 248 veces. También distingue entre elementos faltantes y elementos que en realidad están configurados como indefinidos; para este último, seguirá llamando a la función y pasando un valor indefinido como argumento. Si así es como desea manejar matrices dispersas, .forEach podría ser el camino a seguir, incluso si su traductor admite for... of .

La última opción, que funciona en todas las versiones de JavaScript, es un bucle de recuento explícito. Simplemente cuentas de 0 a uno menos que la longitud y usas el contador como índice. El bucle principal se ve así:

Una ventaja de este enfoque es que puede elegir cómo manejar matrices dispersas; El código anterior ejecutará el cuerpo del bucle en toda su longitud con s configurado en indefinido para cualquier elemento faltante, como for .. of . Si, en cambio, desea procesar solo elementos realmente existentes de una matriz dispersa, como .forEach, puede agregar una verificación simple al índice:

Var i, s, myStringArray = [ "Hola", "Mundo" ], len = myStringArray.length; para (i=0; yo

Asignar el valor de longitud a una variable local (en lugar de incluir la expresión myStringArray.length completa en la condición de bucle) puede tener un impacto significativo en el rendimiento porque omite la búsqueda de propiedades hasta el final cada vez; Cuando uso Rhino en mi máquina, la aceleración es del 43%.

Puede ver que el almacenamiento en caché de longitud se realiza en la cláusula de inicialización del bucle, así:

Var i, len, myStringArray = [ "Hola", "Mundo" ]; para (len = myStringArray.length, i=0; i

La sintaxis for... in mencionada por otros se utiliza para recorrer las propiedades de un objeto; dado que una matriz en JavaScript es solo un objeto con nombres de propiedades numéricos (y una propiedad de longitud actualizada automáticamente), en teoría podrías hacer un bucle en la matriz con él. Pero el problema es que no se limita a valores de propiedades numéricos (recuerde que incluso los métodos son en realidad solo propiedades cuyo valor es un cierre), ni se garantiza que se repita en orden numérico. Por lo tanto, la sintaxis for... in no debe usarse para recorrer matrices.

¡Hola! Continuamos estudiando métodos de matriz y en esta lección veremos métodos para iterar sobre una matriz. Estos métodos le permiten recorrer una matriz y realizar ciertas acciones en sus elementos. Sí, olvidé decir que todos estos métodos no son compatibles con IE 8. Aunque es muy importante ahora que no son compatibles con este navegador, aún así, si desea compatibilidad con IE8, ES5-shim lo ayudará. Y continuaremos

para cada método

Este método se utiliza para recorrer una matriz en un bucle, pero puedes pasarle una función en la que puedes realizar ciertas acciones sobre los elementos de la matriz. Veamos un ejemplo.

Var mas = ["Plátano", "Aguacate", "Zanahoria"]; mas.forEach(function(item, i, mas) ( alert(i + ": " + item + " (matriz: " + mas + ")"); ));

Aquí en el ejemplo, se pasa una función al método forEach, que especifica 3 parámetros:

artículo- elemento de matriz

i— número de elemento de matriz

más— la matriz que se está procesando.

Este método se puede utilizar en lugar de un bucle for para iterar a través de una matriz.

método de filtrado

Este método, al igual que el método forEach, se utiliza para iterar a través de una matriz y se le pasa una función como argumento, pero le permite filtrar la matriz y devuelve una nueva matriz, que contiene solo aquellos elementos para los cuales la función que pasamos a este método devolverá verdadero.

Es un poco confuso, así que veámoslo con un ejemplo.

Var más = ; var positivoNum = mas.filter(function(num) (retorna num > 0; )); documento.write(númeropositivo); // 1,4,3

En el ejemplo hay una matriz con números y necesitamos obtener otra matriz que contenga solo números positivos de la matriz original. Para hacer esto, aplicamos el método de filtro a la matriz y llamamos a una función que verificará cada elemento, es decir, devolverá todos los números positivos y el resultado se almacenará en otra matriz, en el ejemplo es PositiveNum.

método de mapa

El método map crea otra matriz, que consistirá en los resultados de llamar a la función de la matriz original, pero en esta función se llevarán a cabo algunas acciones en los elementos de la matriz original y el resultado aparecerá en la nueva matriz tal como está. Veamos un ejemplo; de lo contrario, creo que no está del todo claro.

Var más = ; var newMas = mas.map(función(elemento) ( devolver elemento*elemento; )); // obtuve una matriz con cuadrados alert(newMas); // 1,4,9

En el ejemplo, hay un arreglo inicial con números, se le aplica el método map, en el cual cada elemento del arreglo se multiplica por sí mismo y el resultado se escribe en otro arreglo. Como resultado, obtenemos una matriz con los cuadrados de los números en la matriz original.

Métodos todos/algunos

Estos métodos verifican si un elemento está presente en la matriz. Lo hacen a través de una función que se les pasa como parámetro, es decir, si esta función devuelve verdadero, entonces el método en sí devolverá verdadero. Además, el método each requiere que cada elemento cumpla la condición de la función, y el método some requiere que al menos uno coincida. Y como siempre, aquí tienes un ejemplo.

Var más = ; función isPositiv(num) ( return num > 0; ) if(mas.every(isPositiv)) ( document.write("La matriz contiene solo números positivos"); ) else( document.write("La matriz contiene al menos uno número negativo "); ) if(mas.some(isPositiv)) ( document.write("La matriz contiene al menos un número positivo"); ) else ( document.write("No hay números positivos en la matriz") ; )

Considere un ejemplo: tenemos una matriz con números positivos y negativos y necesitamos verificar la presencia de al menos un número negativo. Para hacer esto, utilizamos todos y algunos métodos. Creamos una función que devolverá números positivos y luego la pasaremos al método each. Dado que este método devuelve un resultado lógico, se utiliza en declaraciones condicionales. El método each en nuestro ejemplo devolverá falso porque hay números negativos en la matriz, pero el método some devolverá verdadero porque hay al menos un número positivo en la matriz.

reducir/reducirDerecha

Si necesita iterar a través de una matriz, puede usar forEach, for o for...of.

Si necesita recorrer una matriz y devolver datos para cada elemento, utilice map.

Métodos arr.reducir Y arr.reduceDerecha Similar a los métodos anteriores, pero son un poco más complicados. Se utilizan para calcular un valor único basado en toda la matriz.

Sintaxis:

Let valor = arr.reduce(function(valoranterior, elemento, índice, matriz) ( // ... ), );

La función se aplica a su vez a todos los elementos de la matriz y "transfiere" su resultado a la siguiente llamada.

Argumentos:

  • valor anterior: el resultado de la llamada anterior de esta función, igual a inicial en la primera llamada (si se pasa inicial),
  • elemento: el siguiente elemento de la matriz,
  • índice – su índice,
  • matriz: la matriz en sí.

Cuando se llama a una función, el resultado de su llamada al elemento anterior de la matriz se pasa como primer argumento.

Esto suena complicado, pero se vuelve más simple si piensa que el primer argumento "acumula" el resultado de llamadas a funciones anteriores. Cuando termine, se convierte en el resultado de reducir.

Este método es más fácil de entender, como siempre, con un ejemplo.

Aquí obtenemos la suma de todos los elementos de la matriz en una sola línea:

Sea arr = ; let resultado = arr.reduce((suma, actual) => suma + actual, 0); alerta(resultado); // 15

Aquí usamos la opción de reducción más común, que usa solo 2 argumentos.

Echemos un vistazo más de cerca a cómo funciona.

  1. En la primera ejecución, la suma es inicial (el último argumento de reducir), que es 0, y la actual es el primer elemento de la matriz, que es 1. Por lo tanto, el resultado de la función es 1.
  2. La segunda vez que ejecutamos suma = 1, le agregamos el segundo elemento de la matriz (2).
  3. En la tercera ejecución, suma = 3, a lo que agregamos el siguiente elemento, y así sucesivamente...

El flujo de cálculo se ve así:

En forma de tabla, donde cada línea es una llamada de función en el siguiente elemento de la matriz:

suma actual resultado
primera llamada 1 1
segunda llamada 1 2 3
tercer desafío 3 3 6
cuarto desafío 6 4 10
quinto desafío 10 5 15

Aquí puedes ver claramente cómo el resultado de la llamada anterior se pasa al primer argumento de la siguiente.

También podemos omitir el valor inicial:

Sea arr = ; // se elimina el valor inicial (no hay 0 al final) let result = arr.reduce((sum, current) => sum + current); alerta(resultado); // 15

¡El resultado es exactamente el mismo! Esto se debe a que, en ausencia de inicial, el primer elemento de la matriz se toma como el primer valor y la búsqueda comienza desde el segundo.

La tabla de cálculo será la misma menos la primera línea.

Pero tal uso requiere extrema precaución. Si la matriz está vacía, llamar a reducir sin un valor inicial generará un error.

He aquí un ejemplo:

Sea arr = ; // Error: Reducción de una matriz vacía sin valor inicial // si hubiera un valor inicial, reducir lo devolvería para una matriz vacía. arr.reduce((suma, actual) => suma + actual);

Resultados

Entonces, para resumir, analizamos varios métodos para trabajar con matrices en un bucle. Todos estos métodos tienen una cosa en común: todos necesitan pasar una función como argumento.

  • forEach: para recorrer una matriz.
  • filtrar: para filtrar la matriz. Devuelve una nueva matriz filtrada
  • cada/algunos: para verificar la presencia de elementos individuales en la matriz.
  • mapa: para convertir una matriz en una matriz. Devuelve la matriz convertida original.
  • reduce/reduceRight: calcula un valor de toda la matriz, llama a una función en cada elemento y pasa el resultado intermedio entre llamadas. Se puede utilizar para calcular la suma de los elementos de la matriz.

Tareas

Obtener una nueva matriz

Deje que se proporcione la matriz var mas = ["HTML", "CSS", "JavaScript", "Pascal"], debe usar el método map para obtener una nueva matriz que contendrá las longitudes de cada elemento de la matriz original. .

Filtrar la matriz

Hay una matriz var mas = necesitas usar el método de filtro para obtener una matriz que contenga solo números positivos.

Comprobar matriz

Hay una matriz var mas = debe verificar si hay números negativos en la matriz y mostrar el resultado en la pantalla.

Bueno, en conclusión, un breve vídeo sobre métodos para recorrer una matriz.

  • Traducción
  • I. Iterando sobre matrices reales
    1. para cada método y métodos relacionados
    2. en bucle
    3. Uso adecuado del bucle for...in
    4. for...of loop (uso implícito de iterador)
    5. Uso explícito de iterador.
    1. Usar métodos para iterar sobre matrices reales
    2. Convertir a una matriz real
    3. Una nota sobre los objetos en tiempo de ejecución

I. Iterando sobre matrices reales

Por el momento, hay tres formas de iterar sobre los elementos de una matriz real:
  1. método Array.prototype.forEach;
  2. clásico para bucle
  3. un bucle for...in construido “correctamente”.
Además, pronto, con la llegada del nuevo estándar ECMAScript 6 (ES 6), se esperan dos métodos más:
  1. for...of loop (uso implícito de iterador);
  2. uso explícito de iterador.

1. El método forEach y métodos relacionados

Si su proyecto está diseñado para admitir las características del estándar ECMAScript 5 (ES5), puede utilizar una de sus innovaciones: el método forEach.

Ejemplo de uso:
var a = ["a", "b", "c"]; a.forEach(función(entrada) (consola.log(entrada); ));
En general, usar forEach requiere conectar la biblioteca de emulación es5-shim para navegadores que no admiten este método de forma nativa. Estos incluyen IE 8 y versiones anteriores, que todavía se utilizan en algunos lugares.

La ventaja de forEach es que no es necesario declarar variables locales para almacenar el índice y el valor del elemento de la matriz actual, ya que se pasan automáticamente a la función de devolución de llamada como argumentos.

Si te preocupa el posible coste de realizar una devolución de llamada para cada elemento, no te preocupes y lee esto.

ForEach está diseñado para iterar sobre todos los elementos de una matriz, pero además, ES5 ofrece varios métodos más útiles para iterar sobre todos o algunos elementos, además de realizar algunas acciones sobre ellos:

  • each-devuelve verdadero si para cada elemento de la matriz la devolución de llamada devuelve un valor que se puede convertir a verdadero.
  • some: devuelve verdadero si para al menos un elemento de la matriz la devolución de llamada devuelve un valor que se puede convertir a verdadero.
  • filtro: crea una nueva matriz que incluye aquellos elementos de la matriz original para los cuales la devolución de llamada devuelve verdadero.
  • mapa: crea una nueva matriz que consta de los valores devueltos por la devolución de llamada.
  • reducir: reduce una matriz a un solo valor, aplicando una devolución de llamada a cada elemento de la matriz por turno, comenzando con el primero (puede ser útil para calcular la suma de los elementos de la matriz y otras funciones de resumen).
  • reduceRight: funciona de manera similar a reducir, pero itera a través de los elementos en orden inverso.

2. Para bucle

Bueno viejo para las reglas.:

Var a = ["a", "b", "c"]; índice var; para (índice = 0; índice< a.length; ++index) { console.log(a); }
Si la longitud de la matriz es constante a lo largo del bucle y el bucle en sí pertenece a una sección de código crítica para el rendimiento (lo cual es poco probable), entonces puede usar una versión "más óptima" de for que almacene la longitud de la matriz. :

Var a = ["a", "b", "c"]; índice var, len; para (índice = 0, len = a.length; índice< len; ++index) { console.log(a); }
En teoría, este código debería ejecutarse un poco más rápido que el anterior.

Si el orden de los elementos no es importante, entonces puedes ir aún más lejos en términos de optimización y deshacerte de la variable para almacenar la longitud de la matriz, cambiando el orden de búsqueda al revés:

Var a = ["a", "b", "c"]; índice var; para (índice = a.length - 1; índice >= 0; --index) ( console.log(a); )
Sin embargo, en los motores JavaScript modernos, estos juegos de optimización no suelen significar nada.

3. Uso correcto del bucle for...in

Si se le recomienda utilizar un bucle for...in, recuerde que iterar sobre matrices no es para lo que está diseñado. Contrariamente a una idea errónea común, el bucle for...in no itera sobre índices de matriz, sino a través de propiedades enumerables de un objeto.

Sin embargo, en algunos casos, como en la iteración sobre matrices dispersas, for...in puede ser útil, siempre y cuando se tomen precauciones, como se muestra en el siguiente ejemplo:

// a - matriz dispersa var a = ; una = "una"; a = "b"; a = "c"; for (var clave en a) (if (a.hasOwnProperty(clave) && /^0$|^\d*$/.test(clave) && clave<= 4294967294) { console.log(a); } }
En este ejemplo, se realizan dos comprobaciones en cada iteración del bucle:

  1. que el array tiene una propiedad propia llamada clave (no heredada de su prototipo).
  2. esa clave es una cadena que contiene la representación decimal de un número entero cuyo valor es menor que 4294967294. ¿De dónde viene el último número? De la definición de índice de matriz en ES5, que muestra que el índice más alto que puede tener un elemento en una matriz es: (2^32 - 2) = 4294967294.
Por supuesto, dichas comprobaciones consumirán tiempo innecesario al ejecutar el bucle. Pero en el caso de una matriz dispersa, este método es más eficiente que un bucle for, ya que en este caso solo se iteran aquellos elementos que están definidos explícitamente en la matriz. Entonces, en el ejemplo anterior, solo se realizarán 3 iteraciones (para los índices 0, 10 y 10000), frente a 10001 en el bucle for.

Para no escribir un código de verificación tan engorroso cada vez que necesite iterar a través de una matriz, puede escribirlo como una función separada:

Función arrayHasOwnIndex(matriz, clave) ( devuelve array.hasOwnProperty(clave) && /^0$|^\d*$/.test(clave) && clave<= 4294967294; }
Entonces el cuerpo del bucle del ejemplo se reducirá significativamente:

Para (ingrese a) ( if (arrayHasOwnIndex(a, key)) ( console.log(a); ) )
El código de verificación discutido anteriormente es universal y adecuado para todos los casos. Pero en su lugar, puede utilizar una versión más corta, aunque formalmente no del todo correcta, pero adecuada para la mayoría de los casos:

Para (ingrese a) ( if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) ( console.log(a); ) )

4. For...of loop (uso implícito de iterador)

ES6, aún en estado de borrador, debería introducir iteradores en JavaScript.

Iterador es un protocolo implementado por un objeto que define una forma estándar de obtener una secuencia de valores (finita o infinita).
Un iterador es un objeto que define un método next(), una función sin argumentos que devuelve un objeto con dos propiedades:

  1. done (booleano): verdadero si el iterador ha llegado al final de la secuencia iterable. De lo contrario, el valor es falso.
  2. valor: define el valor devuelto por el iterador. Puede no estar definido (faltar) si la propiedad done es verdadera.
Muchos objetos integrados, incl. Las matrices reales tienen iteradores por defecto. La forma más sencilla de utilizar un iterador en matrices reales es utilizar la construcción new for...of.

Ejemplo de uso para... de:

Varval; var a = ["a", "b", "c"]; para (val de a) ( console.log(val); )
En el ejemplo anterior, el bucle for...of llama implícitamente al iterador del objeto Array para obtener cada valor de la matriz.

5. Uso explícito de iterador.

Los iteradores también se pueden usar explícitamente; sin embargo, en este caso el código se vuelve mucho más complicado en comparación con el bucle for...of. Se parece a esto:

Var a = ["a", "b", "c"]; var it = a.entradas(); entrada var; mientras (!(entrada = it.next()).hecho) ( console.log(entrada.valor); )
En este ejemplo, el método Array.prototype.entries devuelve un iterador que se utiliza para mostrar los valores de la matriz. En cada iteración, entrada.valor contiene una matriz del formato [clave, valor].

II. Iterando sobre objetos tipo matriz

Además de las matrices reales, en JavaScript también hay objetos tipo matriz . Lo que tienen en común con los arreglos reales es que tienen una propiedad de longitud y propiedades nombradas como números correspondientes a los elementos del arreglo. Los ejemplos incluyen el DOM de la colección NodeList y la pseudomatriz de argumentos disponibles dentro de cualquier función/método.

1. Usar métodos para iterar sobre matrices reales

Como mínimo, la mayoría, si no todos, los métodos de iteración sobre matrices reales se pueden utilizar para iterar sobre objetos similares a matrices.

Las construcciones for y for...in se pueden aplicar a objetos tipo matriz exactamente de la misma manera que a matrices reales.

ForEach y otros métodos Array.prototype también se aplican a objetos tipo matriz. Para hacer esto necesitas usar Function.call o Function.apply.

Por ejemplo, si desea aplicar forEach a la propiedad childNodes de un objeto Node, debe hacerlo así:

Array.prototype.forEach.call(node.childNodes, function(child) ( // hacer algo con el objeto hijo));
Para que este truco sea más fácil de reutilizar, puedes declarar una referencia al método Array.prototype.forEach en una variable separada y usarla como acceso directo:

// (Suponiendo que todo el código siguiente esté en el mismo ámbito) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) ( // hacer algo con el objeto hijo));
Si un objeto similar a una matriz tiene un iterador, se puede usar explícita o implícitamente para iterar sobre el objeto de la misma manera que para las matrices reales.

2. Convertir a una matriz real

También hay otra forma muy sencilla de iterar sobre un objeto similar a una matriz: convertirlo en una matriz real y utilizar cualquiera de los métodos discutidos anteriormente para iterar sobre matrices reales. Para la conversión, puede utilizar el método genérico Array.prototype.slice, que se puede aplicar a cualquier objeto similar a una matriz. Esto se hace de forma muy sencilla, como se muestra en el siguiente ejemplo:

Var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
Por ejemplo, si quisieras convertir una colección NodeList en una matriz real, necesitarías un código como este:

Var divs = Array.prototype.slice.call(document.querySelectorAll("div"), 0);
Actualizar: Como se indica en los comentarios

12 de marzo de 2016

En JavaScript moderno, existen los llamados "métodos de iteración" que se utilizan para iterar a través de matrices. En este tutorial cubriremos los siguientes métodos:

para cada

El método .forEach() se utiliza para buscar formación. Llama a la llamada función de devolución de llamada, con la ayuda de la cual se pasan tres parámetros item, i, arr, donde:

  • item — elemento de matriz;
  • i es el número de serie de la matriz;
  • arr es la matriz en sí que debe iterarse.

Para que sea más fácil entender cómo utilizar este método, considere un ejemplo:

Var usuario=["admin","contraseña",31]; user.forEach(function(item,i,user)( alert("Valor del artículo No. " + i + " : " + item); ));

Este método se puede utilizar en lugar de un bucle for normal.

filtrar

El método .filter() se usa para filtrar, también usa la función de devolución de llamada, pero crea una nueva matriz si los elementos de la matriz coinciden con el valor verdadero:

Vararr=; var newArr=arr.filter(función(número)( número de retorno< 0; }); alert(newArr); // выведет -34,-4

En este ejemplo, se verifica que los números tengan valores negativos y el resultado es una nueva matriz con estos valores. Puedes proponer tus propias condiciones; no necesariamente tienen que ser números.

todos/algunos

Estos dos métodos son similares entre sí y ambos se usan para verificar una matriz, solo el método .cada() devuelve verdadero si todos los valores de la matriz coinciden con la condición especificada y el método .alguno() devuelve verdadero si al menos un valor coincide con la condición:

Vararr=; alerta (arr.cada (función (número) (número de retorno)< 0; })); // выведет false

Espero que quede claro que si en el ejemplo anterior usamos algún método entonces habríamos mostrado el valor verdadero en lugar de falso.

mapa

El método .map() transforma la matriz y obtiene una nueva a partir de ella. Todo se hace llamando a la función de devolución de llamada:

Vararr=; var newArr=arr.map(función(número)( número de retorno*2; )); alerta(nuevaArr);

En este ejemplo, recibimos una nueva matriz con el doble de valores de los elementos.

reducir/reducirDerecha

Los últimos métodos que veremos son reducir y reducirDerecha. Se utilizan para procesar cada elemento de la matriz mientras se guarda el resultado intermedio. El método recorre cada elemento de izquierda a derecha, reduceRight hace lo contrario. A diferencia de otros métodos, además de la función de devolución de llamada, aquí también se especifica el argumento valorinicial: "valor inicial". Además, la función de devolución de llamada especifica el "resultado intermedio": valor anterior Y artículo actual— elemento actual de la matriz.

Veamos un ejemplo:

Función getSums(arr) ( var resultado = ; if (!arr.length) devuelve resultado; var totalSum = arr.reduceRight(función(suma, elemento) ( resultado.push(suma); devuelve suma + elemento; )); resultado .push(totalSum); devuelve resultado; alerta(getSums()); // 1,3,6,10,15

¿Qué pasó en este ejemplo? Hemos creado una función que nos permite obtener un nuevo array con elementos creados a partir de la suma de los anteriores. Además, el informe de elementos viene desde el final. Y aquí hay un ejemplo más simple en el que creé una función que calcula la suma de elementos en una matriz:

Función getSum(arr) ( var resultado = arr.reduce(function(suma, actual) ( devolver suma + actual )); devolver resultado; ); alerta(obtenerSuma()); Etiquetas: 

22 respuestas

Después de ejecutar esta prueba con la mayoría de los navegadores modernos...

Actualmente la forma más rápida de bucle (y, en mi opinión, la más sintácticamente obvia).

estándar para bucle almacenado en caché de longitud

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

Yo diría que este es definitivamente un caso en el que aplaudo a los desarrolladores de motores JavaScript. El tiempo de ejecución debe optimizarse para claridad, no por conveniencia.

A junio de 2016, varias pruebas en la última versión de Chrome (71% del mercado de navegadores en mayo de 2016 y en aumento):

  • El ciclo más rápido es el ciclo del ciclo., con y sin longitud de caché, lo que proporciona un rendimiento muy similar. (Un bucle for con una longitud almacenada en caché a veces produce mejores resultados que uno que no está almacenado en caché, pero la diferencia es casi insignificante, lo que significa que el motor puede optimizarse a favor del bucle estándar y quizás más simple sin caché).
  • El bucle while con decrementos era aproximadamente 1,5 veces más lento que el bucle for.
  • Un bucle que utiliza una función de devolución de llamada (por ejemplo, forEach estándar) era aproximadamente 10 veces más lento que un bucle for.

Creo que este hilo es demasiado antiguo y los programadores sienten que necesitan almacenar en caché la longitud o usar intersecciones para disminuir hacia atrás para lograr un mejor rendimiento, escribiendo código que sea menos exigente y más propenso a errores que un simple bucle for. Por eso recomiendo:

    Si su aplicación itera a través de muchos elementos, o su código de bucle está dentro de una función que se usa con frecuencia, la respuesta es un bucle directo:

    Para (var i = 0; i< arr.length; i++) { // Do stuff with arr[i] or i }

    Si su aplicación realmente no itera sobre muchos elementos o simplemente necesita hacer pequeñas iteraciones aquí y allá, usar la devolución de llamada estándar forEach o cualquier función similar de su biblioteca JS de elección puede ser más limpio y menos propenso a errores desde el índice. El alcance de la variable es privado y no es necesario utilizar paréntesis para acceder directamente al valor de la matriz:

    Arr.forEach(function(value, index) ( // Hacer cosas con valor o índice ));

    Si realmente necesita combinar unos pocos milisegundos, iterando sobre miles de millones de filas, y la longitud de la matriz no cambiará en el proceso, podría considerar almacenar en caché la longitud en un bucle for. Aunque creo que actualmente no es necesario:

    Para (var i = 0, len = longitud del arreglo; i< len; i++) { // Do stuff with arr[i] }

Estamos apenas en 2018, por lo que una actualización podría ser buena...

Y realmente debería No estoy de acuerdo con la respuesta aceptada.. Depende de diferentes navegadores. algunos hacen forEach más rápido, algunos hacen bucles for y otros prueban todos los métodos http://jsben.ch/mW36e

Arr.forEach(a => ( // ... )

y como puedes ver muchos bucles for(a = 0;...) como for(a = 0;...) vale la pena mencionar que sin variables "var" se definirá globalmente y esto puede tener un impacto significativo velocidad, por lo que será lento.

var arr = arr = new Array(11111111).fill(255); var bancos = [ [ "vacío", () =>< l; a++); }] , ["for-loop", () =>( para(var a = 0, l = longitud del arreglo; a< l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () =>( para(var a = 0, l = longitud del arreglo; a< l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () =>(para(var a = 0; a< arr.length; ++a) var b = arr[a] + 1; }] , ["reverse for-loop", () =>( for(var a = arr.length - 1; a >= 0; --a) var b = arr[a] + 1; )] ,[" while-loop ", () => ( var a = 0 , l = longitud del arreglo;< l) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () =>( var a = arr.length - 1; // CUIDADO hacer ( var b = arr[a] + 1; ) while(a--); )] , ["forEach", () => ( arr.forEach( a => ( var b = a + 1; )); ["for..in (sólo 3,3%)", () => ( var ar = arr.slice(0,arr.length/33) ; for( const a en ar) ( var b = a + 1; )] , ["Dispositivo Duff", () => ( var i = 0; var r = arr.length % 8; var n = (arr .length - r ) / 8; si (r > 0) hacer ( var b = arr + 1; ) mientras que (--r); si (n > 0) hacer ( var b = arr[i] + 1; var c = arr + 1; var e = arr + 1; var g = arr + 1; --n >>> 3; mientras (n);] , ["Dispositivo Duff negativo", () => ( var r = arr.length % 8; var n = (arr.longitud-r) / 8 ; ///Math.floor(arr.longitud / 8); arr[--i] + 1; --r; ) mientras (n)( var b = arr[i] + 1; var c = arr + 1; var d = arr + 1; var e = arr + 1; var f = matriz + 1; var g = matriz + 1; var h = matriz + 1; var j = matriz + 1; banco de funciones(título, f) ( var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log("$(title) tomó $(t1-t0 ) msec"); ) var globalVarTime = bench("for-loop sin "var"", () => ( // Aquí, si olvidas poner "var", las variables serán globales for(a = 0, l = longitud del arreglo;< l; ++a) var b = arr[a] + 1; }); var times = benches.map(function(a) { arr = new Array(11111111).fill(255); return }).sort((a,b) =>ab); var máx = veces; tiempos = tiempos.map(a => (a = (a/max)*100; devuelve a; )); var plantilla = (título, hora, n) => "

" + "$(título) " + " $(Número(tiempo.toFixed(3)))mseg" + "
"; var strRes = times.map(t => plantilla(...t)).join("\n") + "

bucle for sin "var" $(globalVarTime) msec."; var $container = document.getElementById("container"); $container.innerHTML = strRes; body ( color:#fff; fondo:#333; font-family :helvetica; ) cuerpo > div > div ( claro: ambos ) cuerpo > div > div > span ( float:izquierda; ancho:43%; margen:3px 0; text-align:right; ) cuerpo > div > div > span :nth-child(2) ( alineación de texto:izquierda; fondo:naranjaoscuro; animación:showup .37s .111s; -webkit-animation:showup .37s .111s; ) @keyframes showup ( de ( ancho:0; ) ) @-webkit-keyframes showup (desde (ancho:0;))

2014 Hace tiempo

Piensa logicamente.

Mira este

For(var índice = 0, longitud = matriz.longitud; índice< length ; index++) { //do stuff }

  • Necesitas crear al menos 2 variables (índice, longitud)
  • Es necesario comprobar si el indicador de longitud es inferior a
  • Es necesario aumentar el índice
  • el bucle for tiene 3 parámetros

Ahora dime por qué esto debería ser más rápido que:

Longitud var = matriz.longitud; while(--longitud) ( //o longitud-- //hacer cosas)

  • una variable
  • Sin cheques
  • El índice disminuye (las máquinas prefieren esto)
  • Mientras que tiene un solo parámetro

Quedé completamente confundido cuando Chrome 28 mostró que el bucle for era más rápido que el tiempo. debería ser algo así como

"Bueno, todo el mundo usa un bucle for, centrémonos en eso cuando para Chrome".

Pero ahora, en 2014, el bucle while volverá a Chrome. es 2 veces más rápido, en otros navegadores antiguos siempre fue más rápido.

Últimamente he hecho algunas pruebas nuevas. Ahora bien, en el mundo real del entorno, estos códigos cortos no tienen valor y jsperf en realidad no puede ejecutar el bucle while correctamente porque necesita recrear array.length, lo que también lleva tiempo.

NO PUEDO obtener la velocidad real del bucle while en jsperf.

necesitas crear tu propia función y verificarla usando window.performance.now()

Y sí... no hay forma de que un bucle while sea más rápido.

El verdadero problema es el tiempo real de manipulación/reproducción/tiempo de dibujo o como quieras llamarlo.

Por ejemplo, tengo una escena de lienzo donde necesito calcular coordenadas y colisiones... esto se hace entre 10 y 200 microsegundos (no milisegundos). en realidad, se necesitan varios milisegundos para hacer todo. Igual que en DOM.

Hay otra manera súper eficiente de usar loop en algunos casos... por ejemplo para copiar/clonar una matriz

For(var i = array.length; i > 0; arrayCopy[ --i ] = array[ i ] // haciendo cosas);

Tenga en cuenta la configuración de los parámetros:

  • Igual que en el bucle while. solo uso una variable
  • Es necesario comprobar si el índice es mayor que 0;
  • Como puede ver, este enfoque es diferente del bucle habitual que todos usan, ya que estoy haciendo cosas dentro del tercer parámetro y también disminuyendo directamente dentro de la matriz.

Se dice que esto confirma que máquinas como

Escribí que pensé en hacerlo un poco más corto y eliminar algunas cosas inútiles y escribí este usando el mismo estilo:

For(var i = array.length; i--; arrayCopy[ i ] = array[ i ] // haciendo cosas);

Incluso si es más corto, parece que usar i una vez más ralentiza todo. Esto es 1/5 más lento que el bucle for y while anterior.

Nota:; muy importante despues por muuucho sin ()

Incluso si acabo de decirte que jsperf no es la mejor manera de probar scripts. He añadido 2 bucles aquí.

Y aquí hay otra respuesta sobre el rendimiento en javascript.

Esta respuesta debería mostrar formas eficaces de escribir javascript. Entonces, si no puedes leer esto, pregunta y obtendrás una respuesta o lee un libro sobre javascript http://www.ecma-international.org/ecma-262/5.1/

La última revisión de la prueba que preparé (reutilizando una anterior) muestra una cosa.

La longitud del caché no es tan importante, pero no hace daño.

Cada primera ejecución de la prueba vinculada anteriormente (en la pestaña recién abierta) brinda los mejores resultados para los últimos 4 fragmentos (3.°, 5.°, 7.° y 10.° en los gráficos) en Chrome, Opera y Firefox en mi Debian Squeeze de 64 bits ( mi hardware de escritorio). Las ejecuciones posteriores dan un resultado completamente diferente.

Las conclusiones sobre el rendimiento son simples:

  • Vaya a un bucle for (adelante) y verifique con! == en su lugar< .
  • Si no necesita reutilizar la matriz más adelante, entonces un bucle con longitud reducida y cambio de matriz destructivo () también es efectivo.

Actualmente (2011.10), la siguiente plantilla parece ser la más rápida.

Para (var i = 0, len = arr.length; i !== len; i++) ( ... )

Recuerde que el almacenamiento en caché de arr.length no es crítico aquí, por lo que puede simplemente probar i !== arr.length y no habrá ningún impacto en el rendimiento, pero obtendrá un código más corto.

PD: Sé que en un fragmento con shift() se puede usar su resultado en lugar de acceder al elemento 0, pero de alguna manera lo pasé por alto después de reutilizar la revisión anterior (que tenía el valor incorrecto durante los bucles), y luego no lo hice. queremos perder los resultados ya obtenidos.

¿“Mejor” como en puro rendimiento? o rendimiento Y?

El "mejor" rendimiento puro es aquel que utiliza el caché y el operador de prefijo ++ (mis datos: http://jsperf.com/caching-array-length/189)

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

Yo diría que un bucle sin caché es el mejor equilibrio entre el tiempo de ejecución y el tiempo de lectura del programador. Todo programador que comience con C/C++/Java no gastará ms en leer esto.

Para(var i=0; i< arr.length; i++){ // blah blah }

** almacena en caché la longitud de la matriz dentro del bucle, algunos segundos de tiempo se perderán. Depende de los elementos del array, si hay más elementos en el array hay una gran diferencia respecto al tiempo*

SArri; //Formación; para(var i = 0 ; i

SArri; //Formación; for(var i = 0,len = sArr.length ; i< len ; i++) { callArray(sArr[i]); //function call } ***end: 1.354ms***

este es el año 2017 .

Hice algunas pruebas.

Parece que el método while es el más rápido en Chrome.

Parece que el decremento izquierdo (--i) es mucho más rápido que los demás (++i, i--, i++) en Firefox.

Este enfoque consiste en ayunar en promedio. Pero itera la matriz en orden inverso.

Sea i = matriz.longitud; mientras (--i >= 0) ( hacer algo(matriz[i]); )

Si el orden de prioridad es importante, utilice este enfoque.

Sea ii = matriz.longitud; sea ​​yo = 0; mientras yo< ii) { doSomething(array[i]); ++i; }

Siempre escribo en el primer estilo.

Incluso si el compilador es lo suficientemente inteligente como para optimizarlo para matrices, ¿sigue siendo inteligente si usamos DOMNodeList aquí o algún objeto complejo con longitud calculada?

Sé que la pregunta es sobre matrices, pero creo que es una buena práctica escribir todos los bucles con el mismo estilo.

Vararr = ; // La matriz var i = 0; mientras yo< arr.length) { // Do something with arr[i] i++; }

i++ es más rápido que ++i, --i y i -



¿Te gustó el artículo? Compártelo