🖖 Inicio

SERVICIOS

Salir

nochedía

Loops de JavaScript, diferencias entre FOR versus FOREACH

500 palabras
2 minutos
May 17, 2020
blogjavascript

El forEach nos permite programar de modo declarativo (lo cual acostumbra a ser mucho mejor), pero ojo con el await y el async, porque con el forEach no funcionan como esperaríamos

  1. Prólogo
  2. El loop for con arrays y objects
  3. El loop forEach
  4. Await y Async con el forEach

Prólogo

Iterar sobre objects es una de las operaciones más útiles en JavaScript ya que muchas veces los objetos representan la manera más versátil que tenemos para organizar nuestros datos

El problema de utilizar loops es que no es tan sencillo como parece, las opciones de las que disponemos son bastantes y vale la pena conocer las diferencias entre ellas

Aquí compararé el clásico for con el forEach, que pueden parecer lo mismo pero son entre distintos y muy distintos

El loop for con arrays y objects

El loop for nos permite iterar en una secuencia de números

  • En un array estos números pueden ser sus índices para luego tener acceso a sus valores
  • En un object necesitaremos transformar el objeto en array, y el código final resulta una pesadilla

En resumen, este loop ha quedado anticuado aunque es el que (normalmente) ofrece un mayor rendimiento

js
const myArray = [
'kuworking',
'Aprende desarrollo web en kuworking.com',
]
for (let i = 0; i < myArray.length; i++ ) // myArray.length es igual a 2
console.log(myArray[i])
// kuworking
// Aprende desarrollo web en kuworking.com
const myObject = {
name: 'kuworking',
description: 'Aprende desarrollo web en kuworking.com',
}
for (let i = 0; i < Object.entries(myObject).length; i++) {
console.log(Object.keys(myObject)[i])
console.log(myObject[Object.keys(myObject)[i]])
}
// name
// description
// kuworking
// Aprende desarrollo web en kuworking.com

Para iterar arrays y objetos tenemos otros loops más modernos, los tienes en la entrada Loops de JavaScript, diferencias entre FOR..IN versus FOR..OF

Pero aquí hablaremos del forEach, un loop distinto a todos los demás

El loop forEach

Y por qué es distinto a los demás? Porque nos permite programar de un modo funcional o declarativo y no imperativo

Diferencias?

  • Con el imperativo lo primero que lees es cómo lo haces, y luego ves el qué
  • Con el funcional lo primero que lees es el qué, y luego ves el cómo

Es algo tan básico como que delante de una estructura for con sus paréntesis y sus variables tendrás sí o sí que pararte y entretenerte si quieres saber qué pasa allí

Con un foreach ya sabrás la variable y que hay un foreach, no te hará falta entretenerte para tener una idea básica de lo que ocurre

Y esto te permite

  • Leer el código más rápido
  • Escribir el código más rápido

Funciona así

js
const myObject = {
name: 'kuworking',
description: 'Aprende desarrollo web en kuworking.com',
}
Object.entries(myObject).forEach(el => console.log(el))
// ["name", "kuworking"]
// ["description", "Aprende desarrollo web en kuworking.com"]

Hasta aquí la diferencia conceptual

Pero hay una diferencia práctica que importa y mucho

Await y Async con el forEach

Este código funciona como esperamos (voy a utilizar un for..of por comodidad)

js
const timeout = (method, ms) =>
new Promise(resolve =>
setTimeout(() => {
method()
resolve()
}, ms)
)
const myObject = {
name: 'kuworking',
description: 'Aprende desarrollo web en kuworking.com',
}
;(async () => {
for await (const [key, value] of Object.entries(myObject)) {
await timeout(() => console.log('key -> ' + key), 1000)
console.log('value: -> ' + value)
}
})()
// "key -> name"
// "value: -> kuworking"
// "key -> description"
// "value: -> Aprende desarrollo web en kuworking.com"

Es decir, esperamos 1 segundo, luego tenemos una impresión de la primera pareja de valores en orden, luego esperamos otro segundo, y entonces nos aparecen la segunda pareja de valores

Pero si queremos hacer lo mismo con forEach vemos que no funciona

js
const timeout = (method, ms) =>
new Promise(resolve =>
setTimeout(() => {
method()
resolve()
}, ms)
)
const myObject = {
name: 'kuworking',
description: 'Aprende desarrollo web en kuworking.com',
}
Object.entries(myObject).forEach(async ([key, value]) => {
await timeout(() => console.log('key -> ' + key), 1000)
console.log('value: -> ' + value)
})
// "value: -> kuworking"
// "value: -> Aprende desarrollo web en kuworking.com"
// "key -> name"
// "key -> description"

Aquí nos siguen apareciendo por orden, pero nos aparecen las 2 parejas de valores al mismo tiempo, en lugar de esperarnos 2 segundos nos esperamos sólo 1 segundo

Haz la prueba y pon un valor de 10 segundos

  • Con el for of esperarías 10 segundos, luego una pareja, luego 10 segundos más, luego la otra pareja
  • Con el forEach esperarás 10 segundos y verás las 2 parejas en la consola

Y eso por qué pasa?

Porque cada loop de forEach es en realidad una función independiente, no forma parte de un loop

En otras palabras, el forEach lanza tantas funciones como elementos tenga en el loop, y estas se ejecutan en paralelo, no hay ninguna secuencia

Conclusión?

Si necesitas ejecutar el loop de forma secuencial, con forEach no puedes

Tu elección es el loop for of, y si no puedes con la programación imperativa, tu amigo es reduce()

Qué tal la entrada?
👌 Bien 🙌🙌
👍 Bien, pero algunas cosas podrían explicarse mejor 😬
🤷‍♂️ Da por sentadas demasiadas cosas 😒
🤷‍♂️ A ver, hay poca chicha 😬
🤷‍♂️ Los ejemplos no son muy claros 🙇‍♂️
🤷‍♂️ No se entiende, está mal escrito 👎
✍️ Hay errores, revísalo en cuanto puedas 🙏

Newsletter de kuworking, un correo de tanto en cuanto

Quizá te interese

Privacidad
by kuworking.com
[ 2020 >> kuworking ]