Por qué puede 't romper un bucle forEach / tamaño de bytes JS

Recientemente tuve una entrevista de codificación que involucró evaluar un esquema contra otro. Los detalles no son tan importantes, pero una cosa que salió de ella (en medio de la entrevista) fue que no puedes salir de un bucle forEach(). Había olvidado ese pequeño detalle y probablemente arruinó mis posibilidades de ser contratado. ¡Después de leer esto, con suerte, no cometerás el mismo error que yo cometí! No seas como yo.

https://media.giphy.com/media/nRkQduJDZ43bW/giphy.gif

Si prefieres mirar en lugar de leer, ¡echa un vistazo a la versión en video de esto!

MDN Conoce todo

Según lo indicado por MDN:

No hay forma de detener o romper un bucle forEach() que no sea lanzando una excepción. Si necesita tal comportamiento, el método forEach () es la herramienta incorrecta

Eso es algo sass hardcore proveniente de los documentos MDN. Sin embargo, tienen razón, saber qué herramienta elegir es importante.

Antes de profundizar demasiado en por qué no puedes salir de un forEach(), examinemos qué es un bucle y de dónde vino forEach().

¿Qué es un Bucle

Un bucle en la programación resuelve un problema bastante común: Necesito ejecutar el mismo código contra todos estos datos. En pocas palabras, es:

Repetir el mismo código una y otra vez (en bucle) hasta llegar a un estado final definido.

El Problema

En aras de la comparación, vamos a resolver el mismo problema utilizando los diversos tipos de bucle. Aquí está el problema:

Compare dos matrices y vea si los elementos en ellas son los mismos.

Aquí están los datos que vamos a comparar:

 const jedis = const sith = 

Tenemos dos matrices, ambas con un par de nombres. Probablemente notarás que Anakin es a la vez un Jedi y un Sith. Este es un ejemplo trivial, sin embargo, no muy lejos de lo que me probaron durante mi entrevista.

La Antigua Forma A

Lo que no quiero que obtengas de este artículo es que un bucle es mejor que otro. Todos ellos ofrecen soluciones de programación únicas y tienen un lugar para casos de uso específicos. El truco es saber cuál usar y cuándo.

Tradicional For Loop

Si alguna vez has tomado algún tipo de curso de programación, probablemente hayas estado expuesto a nuestro buen amigo el for loop. Ha sido una herramienta útil para los programadores durante mucho tiempo y sigue siendo útil hoy en día. Resolvamos nuestro problema usándolo.

// Our data again, for referenceconst jedis = ;const sith = ;// start our loop, define our iterator variablefor (let i = 0; i < jedis.length; i++) { // create a variable we can reference const thisJedi = jedis; // see if the item in the array we are testing exists if (sith.includes(thisJedi)) { // If it does exist, then that jedi is also a sith console.log(`${thisJedi} is also a Sith`); // we can exit out break; } console.log(`${thisJedi} is not a Sith`);}

El bucle for ofrece una forma bastante práctica de salir de nuestro código si cumple con una condición que elijamos. Esto es inmensamente útil cuando se repasa una TONELADA de datos. Ha sido muy útil para resolver algunos de los problemas del Proyecto Euler, específicamente este.

El Nuevo Otro Camino

Entre otras cosas, forEach() se estampó en la especificación en 2009 junto con todas las demás bondades que se nos dieron en ES5. Sirve como un método práctico para escribir código limpio que itera fácilmente sobre elementos en una matriz.

¿Qué está haciendo?

Un bucle forEach() es una función que ejecuta otra función (devolución de llamada) en cada elemento de una matriz. Definimos lo que sucede en esa función de devolución de llamada. JS es lo suficientemente bueno para darnos tres parámetros en esa función:

  1. El elemento en el array
  2. El índice del elemento
  3. Todo el array

Echemos un vistazo a nuestro problema usando un bucle forEach() en su lugar. He incluido los tres parámetros en la función, pero solo estamos usando el primero, el elemento, que estoy nombrando jedi

 // We have to create a global state variable to keep track of what is happening let matching // loop over array jedis.forEach((jedi,index,array) => { // check to see if jedi is in sith if(!sith.includes(jedi)) { // if it isn't, set global variable to false matching = false } // it keeps going... }) console.log(matching) // false

Si tiene más sentido, puede refactorizar la función de devolución de llamada en una función con nombre. Creo que lo hace un poco más legible. También nos permite reutilizar esta función donde queramos. Yay programación funcional!

 let matching function isJediAlsoSith(jedi,index,array) { if(!sith.includes(jedi)) { matching = false } } jedis.forEach(isJediAlsoSith)

Nuestra solución esencialmente hace lo mismo. La única diferencia es que se sigue ejecutando hasta que llega al final de la matriz jedis. Para una variedad de tamaño tan pequeño, dudo que marque una gran diferencia de rendimiento.

¿Pero por qué?

Esto finalmente nos lleva a la respuesta a nuestra pregunta, ¿por qué no podemos salir de un bucle forEach()? Es porque el bucle está ejecutando esa función de devolución de llamada sobre cada elemento, por lo que incluso si escribe un return, solo regresa en esa instancia de la función. Sigue adelante. En el caso de la función forEach(), no hace nada con el código devuelto. Tenga en cuenta que no es el caso de algunos de los otros métodos de matriz.

Además, debido a esto, break o continue no son declaraciones válidas.

Otras formas

Hay bastantes tipos diferentes de bucles. Todos tienen diferentes propósitos y yo recomendaría investigar cada uno de ellos. No siempre necesitas un bucle forEach().

https://media.giphy.com/media/tnwuVMx6n1VtK/giphy.gif

forEach () vs map ()

Probablemente, los métodos de matriz más comunes que aparecen en los tutoriales son forEach() y map() . La mayor diferencia entre los dos es que map devolverá un nuevo Array, mientras que forEach() no.

Bucles tradicionales

Bucle while

Métodos de matriz

Matriz.forEach ()

Array.map ()

Array.filter ()

Array.reduce ()

Array.reduceRight ()

Array.cada Array

.un array()

.indexOf ()

Array.lastIndexOf ()

Array.Array find()

.findIndex()

Bucles de objetos iterables (incluidos arreglos)

para in

para of

Esta es la Forma

Baby Yoda

Como se mencionó anteriormente en los documentos MDN increíblemente atrevidos, eligiendo la herramienta correcta es primordial para el éxito. El número de opciones puede parecer un poco abrumador al principio, pero me gusta tomar el enfoque de: «si funciona, es la herramienta correcta.»

En términos generales, puedes refactorizar tu código hasta la muerte, pero entonces estás perdiendo el tiempo, podrías estar construyendo cosas. En el caso de mi entrevista, estaba usando la herramienta correcta, de la manera equivocada. Si hubiera sabido recordar que no puedes salir de un bucle forEach, las cosas probablemente habrían resultado diferentes️️.

Si tiene alguna información adicional compartida, ¡déjela en los comentarios a continuación!

Como siempre, feliz codificación.

Plugs

¡Estoy escribiendo un libro sobre diseño gráfico y cómo se relaciona con el desarrollo de software! Si estás interesado, regístrate aquí para recibir actualizaciones.

https://digitalnutt.substack.com/p/coming-soon?r=34slo&utm_campaign=post&utm_medium=web&utm_source=copy

Música

¡También escribo música! Échale un vistazo aquí: Spotify / Youtube / Apple Music

Soporte

Si te gusta este artículo y quieres ver más, la mejor manera de hacerlo es suscribirte / seguirme aquí. ¡Si te sientes amable, puedes comprarme un café!



+