Corto circuito Array.forEach como llamar a break

[1,2,3].forEach(function(el) { if(el === 1) break; }); 

¿Cómo puedo hacer esto usando el nuevo método forEach en JavaScript? He intentado return; , return false; y break break choques y return no hace más que continuar la iteración.

29 Solutions collect form web for “Corto circuito Array.forEach como llamar a break”

No hay una habilidad incorporada para break por cada forEach . Para interrumpir la ejecución, tendría que lanzar una excepción de algún tipo. p.ej.

 var BreakException = {}; try { [1, 2, 3].forEach(function(el) { console.log(el); if (el === 2) throw BreakException; }); } catch (e) { if (e !== BreakException) throw e; } 

Ahora hay una forma aún mejor de hacerlo en ECMAScript2015 (también conocido como ES6) utilizando el nuevo bucle for . Por ejemplo, este código no imprime los elementos de la matriz después del número 5:

 let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; for (let el of arr) { console.log(el); if (el === 5) { break; } } 

Puedes usar todos los métodos:

 [1,2,3].every(function(el) { return !(el === 1); }); 

ES6

 [1,2,3].every( el => el !== 1 ) 

para usar el viejo navegador:

 if (!Array.prototype.every) { Array.prototype.every = function(fun /*, thisp*/) { var len = this.length; if (typeof fun != "function") throw new TypeError(); var thisp = arguments[1]; for (var i = 0; i < len; i++) { if (i in this && !fun.call(thisp, this[i], i, this)) return false; } return true; }; } 

Más detalles aquí .

Cotización de la documentación MDN de Array.prototype.forEach() :

No hay forma de detener o interrumpir un forEach() no sea lanzar una excepción. Si necesita tal comportamiento, el método .forEach() es la herramienta incorrecta , use un bucle plano en su lugar. Si está probando los elementos de la matriz para un predicado y necesita un valor de retorno booleano, puede usar every() o some() lugar.

Para su código (en la pregunta), como lo sugiere @bobince, use Array.prototype.some() lugar. Se adapta muy bien a tu caso de uso.

Array.prototype.some() ejecuta la función de callback una vez para cada elemento presente en la matriz hasta que encuentra uno en el que la callback devuelve un valor verdadero (un valor que se convierte en verdadero cuando se convierte a un valor Boolean ). Si se encuentra un elemento de este tipo, some() devuelve inmediatamente true. De lo contrario, some() devuelve false. la callback se invoca solo para los índices de la matriz que tienen valores asignados; no se invoca para los índices que se han eliminado o que nunca se han asignado valores.

Desafortunadamente, en este caso será mucho mejor si no usa forEach . En su lugar, use un bucle for regular y ahora funcionará exactamente como lo esperaría.

 var array = [1, 2, 3]; for (var i = 0; i < array.length; i++) { if (array[i] === 1){ break; } } 

Considere utilizar each método de jquery , ya que permite devolver una función de callback interna falsa:

 $.each(function(e, i) { if (i % 2) return false; console.log(e) }) 

Las bibliotecas Lodash también proporcionan el método takeWhile que se puede encadenar con map / reduce / fold, etc.

 var users = [ { 'user': 'barney', 'active': false }, { 'user': 'fred', 'active': false }, { 'user': 'pebbles', 'active': true } ]; _.takeWhile(users, function(o) { return !o.active; }); // => objects for ['barney', 'fred'] // The `_.matches` iteratee shorthand. _.takeWhile(users, { 'user': 'barney', 'active': false }); // => objects for ['barney'] // The `_.matchesProperty` iteratee shorthand. _.takeWhile(users, ['active', false]); // => objects for ['barney', 'fred'] // The `_.property` iteratee shorthand. _.takeWhile(users, 'active'); // => [] 

En su ejemplo de código, parece que Array.prototype.find es lo que está buscando: Array.prototype.find () y Array.prototype.findIndex ()

 [1, 2, 3].find(function(el) { return el === 2; }); // returns 2 

Si desea utilizar la sugerencia de Dean Edward y lanzar el error StopIteration para salir del bucle sin tener que detectar el error, puede usar la siguiente función ( originalmente desde aquí ):

 // Use a closure to prevent the global namespace from be polluted. (function() { // Define StopIteration as part of the global scope if it // isn't already defined. if(typeof StopIteration == "undefined") { StopIteration = new Error("StopIteration"); } // The original version of Array.prototype.forEach. var oldForEach = Array.prototype.forEach; // If forEach actually exists, define forEach so you can // break out of it by throwing StopIteration. Allow // other errors will be thrown as normal. if(oldForEach) { Array.prototype.forEach = function() { try { oldForEach.apply(this, [].slice.call(arguments, 0)); } catch(e) { if(e !== StopIteration) { throw e; } } }; } })(); 

El código anterior le dará la capacidad de ejecutar código como el siguiente sin tener que hacer sus propias cláusulas try-catch:

 // Show the contents until you get to "2". [0,1,2,3,4].forEach(function(val) { if(val == 2) throw StopIteration; alert(val); }); 

Una cosa importante a recordar es que esto solo actualizará la función Array.prototype.forEach si ya existe. Si no existe ya, no lo modificará.

Respuesta corta: use for...break para esto o cambie su código para evitar romper forEach . No use .some() o .every() para emular for...break . Vuelva a escribir su código para evitar for...break bucle, o usar for...break . Cada vez que usas estos métodos for...break alternativa Dios mata al gatito.

Respuesta larga:

.some() y .every() devuelven ambos valores boolean , .some() devuelve true si hay algún elemento para el que la función pasada devuelve true , todo devuelve false si hay algún elemento para el que la función pasada devuelve false . Esto es lo que significan las funciones. Usar funciones para lo que no significan es mucho peor que usar tablas para maquetar en lugar de CSS, porque frustra a todos los que leen tu código.

Además, la única forma posible de utilizar estos métodos como alternativa a la for...break es hacer efectos secundarios (cambiar algunas variables fuera de la función de callback .some() ), y esto no es muy diferente de la for...break .

Por lo tanto, usar .some() o .every() for...break alternativa de bucle de for...break no está exenta de efectos secundarios, esto no es mucho más limpio que la for...break , esto es frustrante, por lo que no es mejor.

Siempre puede volver a escribir su código para que no haya necesidad for...break . Puede filtrar la matriz usando .filter() , puede dividir la matriz usando .slice() y así sucesivamente, y luego usar .forEach() o .map() para esa parte de la matriz.

Encontré esta solución en otro sitio. Puedes envolver el forEach en un escenario de prueba / captura.

 if(typeof StopIteration == "undefined") { StopIteration = new Error("StopIteration"); } try { [1,2,3].forEach(function(el){ alert(el); if(el === 1) throw StopIteration; }); } catch(error) { if(error != StopIteration) throw error; } 

Más detalles aquí: http://dean.edwards.name/weblog/2006/07/enum/

Esto es algo que se me ocurrió para resolver el problema … Estoy bastante seguro de que soluciona el problema que tenía el autor de la pregunta original:

 Array.prototype.each = function(callback){ if(!callback) return false; for(var i=0; i 

Y luego lo llamarías usando:

 var myarray = [1,2,3]; myarray.each(function(item, index){ // do something with the item // if(item != somecondition) return false; }); 

Devolver falso dentro de la función de callback causará una interrupción. Déjame saber si eso realmente no funciona.

Si no necesita acceder a su matriz después de la iteración, puede rescatarla estableciendo la longitud de la matriz en 0. Si todavía la necesita después de su iteración, puede clonarla utilizando la división.

 [1,3,4,5,6,7,8,244,3,5,2].forEach(function (item, index, arr) { if (index === 3) arr.length = 0; }); 

O con un clon:

 var x = [1,3,4,5,6,7,8,244,3,5,2]; x.slice().forEach(function (item, index, arr) { if (index === 3) arr.length = 0; }); 

Que es una solución mucho mejor que lanzar errores aleatorios en su código.

Este es un bucle for, pero mantiene la referencia del objeto en el bucle al igual que un forEach () pero se puede romper.

 var arr = [1,2,3]; for (var i = 0, el; el = arr[i]; i++) { if(el === 1) break; } 

Yo uso nullhack para ese propósito, intenta acceder a la propiedad de null , que es un error:

 try { [1,2,3,4,5] .forEach( function ( val, idx, arr ) { if ( val == 3 ) null.NULLBREAK; } ); } catch (e) { // e < => TypeError: null has no properties } // 

Si desea mantener su syntax de forEach , esta es una manera de mantenerla eficiente (aunque no tan buena como un bucle regular). Verifique de inmediato si hay una variable que sepa si quiere salir del ciclo.

Este ejemplo utiliza una función anónima para crear un scope de función alrededor del forEach que necesita para almacenar la información realizada .

 (function(){ var element = document.getElementById('printed-result'); var done = false; [1,2,3,4].forEach(function(item){ if(done){ return; } var text = document.createTextNode(item); element.appendChild(text); if (item === 2){ done = true; return; } }); })(); 
 

Lo sé no de la manera correcta. No es romper el bucle. Es un jugad

 let result = true; [1, 2, 3].forEach(function(el) { if(result){ console.log(el); if (el === 2){ result = false; } } }); 

Como se mencionó anteriormente, no puedes romper .forEach() .

Aquí hay una forma un poco más moderna de hacer un foreach con los iteradores ES6. Le permite obtener acceso directo al index / value al iterar.

 const array = ['one', 'two', 'three']; for (const [index, val] of array.entries()) { console.log('item:', { index, val }); if (index === 1) { console.log('break!'); break; } } 

Salida:

 item: { index: 0, val: 'one' } item: { index: 1, val: 'two' } break! 

Campo de golf

  • Array.prototype.entries()
  • Iteradores y generadores
  • Tarea de destrucción

Otro enfoque mas

  var wageType = types.filter(function(element){ if(e.params.data.text == element.name){ return element; } }); console.dir(wageType); 

Otro concepto que se me ocurrió:

 function forEach(array, cb) { var shouldBreak; function _break() { shouldBreak = true; } for (var i = 0, bound = array.length; i < bound; ++i) { if (shouldBreak) { break; } cb(array[i], i, array, _break); } } // Usage forEach(['a','b','c','d','e','f'], function (char, i, array, _break) { console.log(i, char); if (i === 2) { _break(); } }); 

Utilice la función array.prototype.every , que le proporciona la utilidad para interrumpir el bucle. Vea el ejemplo aquí Documentación de Javascript en la red de desarrolladores de Mozilla

De acuerdo con @bobince, upvoted.

Además, para su información:

Prototype.js tiene algo para este propósito:

  

$break será capturado y manejado por Prototype.js internamente, rompiendo el ciclo “cada uno” pero sin generar errores externos.

Ver Prototype.JS API para más detalles.

jQuery también tiene una forma, simplemente devuelve falso en el controlador para interrumpir el ciclo temprano:

  

Ver jQuery API para más detalles.

Esto no es lo más eficiente, ya que aún tienes todos los elementos en el ciclo, pero pensé que valdría la pena considerar el muy simple:

 let keepGoing = true; things.forEach( (thing) => { if (noMore) keepGoing = false; if (keepGoing) { // do things with thing } }); 

Puedes seguir el siguiente código que me funciona:

  var loopStop = false; YOUR_ARRAY.forEach(function loop(){ if(loopStop){ return; } if(condition){ loopStop = true; } }); 

Prefiero usar for in

 var words = ['a', 'b', 'c']; var text = ''; for (x in words) { if (words[x] == 'b') continue; text += words[x]; } console.log(text); 

Si necesita una ruptura basada en el valor de los elementos que ya están en su matriz como en su caso (es decir, si la condición de ruptura no depende de la variable de tiempo de ejecución que puede cambiar después de que la matriz tenga asignados sus valores de elementos), también puede usar la combinación de slice () y indexOf () de la siguiente manera.

Si necesitas romper cuando forEach llega a ‘Apple’ puedes usar

 var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; var fruitsToLoop = fruits.slice(0, fruits.indexOf("Apple")); // fruitsToLoop = Banana,Orange,Lemon fruitsToLoop.forEach(function(el) { // no need to break }); 

Como se indica en W3Schools.com, el método slice () devuelve los elementos seleccionados en una matriz, como un nuevo objeto de matriz. La matriz original no se cambiará.

Véalo en JSFiddle

Espero que ayude a alguien.

prueba con “encontrar”:

 var myCategories = [ {category: "start", name: "Start", color: "#AC193D"}, {category: "action", name: "Action", color: "#8C0095"}, {category: "exit", name: "Exit", color: "#008A00"} ]; function findCategory(category) { return myCategories.find(function(element) { return element.category === category; }); } console.log(findCategory("start")); // output: { category: "start", name: "Start", color: "#AC193D" } 

Si realmente te gusta forEach , creo que está bien imitar continue esta manera;

 arr.forEach(x=> { if(x>4) return; // some heavy code down below }); 

Pero incluso si adora forEach , no use hacks para simular un break , solo use el bucle regular. De hecho, se me ocurrió una solución inteligente, pero ten en cuenta que no es agradable ya que es una entrada mutada . Si no le importa en absoluto mutar los datos proporcionados, puede usarlos, pero en la mayoría de los casos lo hace .

 arr.forEach(x=> { if (x>4) {arr.length=0; return;} // some heavy code might be here }); 
 var Book = {"Titles":[ { "Book3" : "BULLETIN 3" } , { "Book1" : "BULLETIN 1" } , { "Book2" : "BULLETIN 2" } ]} var findbystr = function(str) { var return_val; Book.Titles.forEach(function(data){ if(typeof data[str] != 'undefined') { return_val = data[str]; } }, str) return return_val; } book = findbystr('Book1'); console.log(book); 

La respuesta correcta depende de por qué quieres hacer esto.

Si lo que desea es: “una forma tan limpia y concisa de salir de forEach() como sea posible, dado que no se permite la break , puede redefinir Array.forEach () para permitirle hacer esto:

 [1,2,3,4,5].forEach((x,i,stop) => { // x and i are the standard 2 args if (x > 3) { stop() // You could call it 'end', 'brk' or whatever... } console.log(x) }) 

Aquí está la anulación, tenga en cuenta que forEach() normalmente pasa dos parámetros: el objeto iterado actualmente y el índice. Solo estamos agregando un tercero:

 Array.prototype.forEach = function(fn) { var StopIteration = new Error("StopIteration"); var len = this.length; function stop() { throw StopIteration; } for (i=0;i 

Puede usar el nombre que desee (excepto break , o cualquier otra palabra clave reservada, ¡no hay suerte!)

(En un proyecto real, debes elegir una de las respuestas súper elevadas. Solo estoy agregando esto porque algunas personas pueden encontrar el concepto útil en otras aplicaciones).

  • Cómo dibujar millones de puntos en google maps?
  • ¿Cómo agrupar o combinar esta matriz de objects en javascript?
  • ¿Cuál es la diferencia entre una copy superficial y una copy profunda con matrices de JavaScript?
  • cómo excluir algunos elementos de javascript Array.map () callback
  • Función que devuelve una matriz de combinaciones de matriz
  • Clasificar matriz de objects por longitud de propiedad
  • ¿Por qué la matriz todavía tiene una longitud distinta de cero después de la eliminación?
  • La manera más eficiente de eliminar de la matriz?
  • Javascript tiene muchos buenos JS marco (como Node.js AngularJS Vue.js React.js) es el mejor lenguaje de script.