Come cortocircuitare Array.forOgni piacere chiamare break?

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

Come posso farlo usando il nuovo metodo forEach in JavaScript? Ho provato “return”, “return false” e “break”. Break si arresta e il ritorno non fa altro che continuare l’iterazione.

Non esiste alcuna abilità forEach per l’ forEach di forEach . Per interrompere l’esecuzione dovresti generare un’eccezione di qualche tipo. per esempio.

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

Ora c’è un modo ancora migliore per farlo in ECMAScript2015 (alias ES6) usando il nuovo ciclo for . Ad esempio, questo codice non stampa gli elementi dell’array dopo il numero 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; } } 

Puoi usare ogni metodo:

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

per il supporto del browser precedente utilizzare:

 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; }; } 

maggiori dettagli qui .

Citando dalla documentazione MDN di Array.prototype.forEach() :

Non esiste alcun modo per interrompere o interrompere un ciclo forEach() diverso da un’eccezione. Se hai bisogno di un simile comportamento, il metodo .forEach() è lo strumento sbagliato , usa invece un ciclo semplice. Se stai testando gli elementi dell’array per un predicato e hai bisogno di un valore di ritorno booleano, puoi usare invece every() o some() .

Per il tuo codice (nella domanda), come suggerito da @bobince, usa invece Array.prototype.some() . Si adatta molto bene al tuo caso d’uso.

Array.prototype.some() esegue la funzione di callback una volta per ciascun elemento presente nell’array finché non ne trova uno in cui il callback restituisce un valore di verità (un valore che diventa true quando viene convertito in un Boolean ). Se viene trovato un tale elemento, some() restituisce immediatamente true. Altrimenti, some() restituisce false. la callback è invocata solo per gli indici dell’array che hanno assegnato valori; non è invocato per gli indici che sono stati cancellati o che non sono mai stati assegnati valori.

Sfortunatamente in questo caso sarà molto meglio se non usi forEach . Usa invece un ciclo for regolare e ora funzionerà esattamente come ti aspetteresti.

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

Considera di utilizzare each metodo di jquery , poiché consente di restituire false funzioni di callback interne:

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

Le librerie Lodash forniscono anche il metodo takeWhile che può essere incatenato con map / reduce / fold ecc:

 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'); // => [] 

Se desideri utilizzare il suggerimento di Dean Edward e lanciare l’errore StopIteration per uscire dal ciclo senza dover rilevare l’errore, puoi utilizzare la seguente funzione ( originariamente da qui ):

 // 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; } } }; } })(); 

Il codice sopra ti darà la possibilità di eseguire codice come il seguente senza dover fare le tue clausole 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 da ricordare è che questo aggiornerà solo la funzione Array.prototype.for.Every se esiste già. Se non esiste già, non lo modificherà.

Dal tuo esempio di codice, sembra che Array.prototype.find sia quello che stai cercando: Array.prototype.find () e Array.prototype.findIndex ()

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

Risposta breve: utilizzare for...break per questo o modificare il codice per evitare la rottura di forEach . Non usare .some() o .every() per emulare for...break . Riscrivi il tuo codice per evitare for...break ciclo di for...break o utilizzarlo for...break . Ogni volta che usi questi metodi come for...break alternativa Dio uccide il gattino.

Risposta lunga:

.some() e .every() restituiscono entrambi valore boolean , .some() restituisce true se esiste un elemento per cui la funzione passata restituisce true , ogni restituisce false se esiste un elemento per cui la funzione passata restituisce false . Questo è ciò che significano queste funzioni. Usare le funzioni per ciò che non significa è molto peggio, quindi usare le tabelle per il layout invece del CSS, perché vanifica chiunque legga il tuo codice.

Inoltre, l’unico modo ansible di usare questi metodi for...break alternativa for...break è creare effetti secondari (modificare alcuni vars al di fuori della funzione di callback .some() ), e questo non è molto diverso da for...break .

Quindi, usando .some() o .every() for...break quanto for...break alternativa al ciclo di for...break non è priva di effetti collaterali, questo non è molto più pulito allora for...break , questo è frustrante, quindi questo non è meglio.

Puoi sempre riscrivere il tuo codice in modo che non ci sia bisogno for...break . Puoi filtrare l’array usando .filter() , puoi dividere l’array usando .slice() e così via, quindi usa .forEach() o .map() per quella parte dell’array.

Ho trovato questa soluzione su un altro sito. È ansible eseguire il wrapping di forEach in uno scenario try / catch.

 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; } 

Maggiori dettagli qui: http://dean.edwards.name/weblog/2006/07/enum/

Se non è necessario accedere all’array dopo l’iterazione, è ansible eseguire il salvataggio impostando la lunghezza dell’array su 0. Se è ancora necessario dopo l’iterazione, è ansible clonarlo utilizzando slice ..

 [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 clone:

 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; }); 

Quale è una soluzione molto migliore quindi lanciando errori casuali nel codice.

Questo è un ciclo for, ma mantiene il riferimento all’object nel loop proprio come un forEach (), ma puoi uscire.

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

Questo è solo qualcosa che ho trovato per risolvere il problema … Sono abbastanza sicuro che risolve il problema che il richiedente originale aveva:

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

E poi lo chiameresti usando:

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

Restituire false all'interno della funzione di callback causerà un'interruzione. Fammi sapere se questo in realtà non funziona.

Io uso nullhack per questo scopo, prova ad accedere alla proprietà di null , che è un errore:

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

Un altro concetto che ho trovato:

 function forEach(array, cb) { var breakOnNext = false; function _break() { breakOnNext = true; } for (var i = 0, bound = array.length; i < bound; ++i) { if (breakOnNext) { break; } cb(array[i], i, array, _break); } } 

Uso:

 forEach(['a','b','c','d'], function (e, i, array, _break) { console.log(e, i); if (e === 'b') { _break(); } }); 

Potrebbe essere necessario qualche ritouch, in particolare per supportare l'iterazione della proprietà dell'object.

Se si desidera mantenere la syntax forEach , questo è un modo per mantenerlo efficiente (sebbene non buono come un normale ciclo per). Controlla immediatamente una variabile che sappia se vuoi uscire dal ciclo.

In questo esempio viene utilizzata una funzione anonima per la creazione di un ambito della funzione attorno a forEach che è necessario memorizzare le informazioni completate.

 (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; } }); })(); 
 

Come accennato in precedenza, non è ansible interrompere .forEach() .

Ecco un modo un po ‘più moderno di fare un foreach con Iterator ES6. Ti consente di ottenere l’accesso diretto index / value durante l’iterazione.

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

Produzione:

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

link

  • Array.prototype.entries()
  • Iteratori e generatori
  • Incarico distruttivo

Utilizzare la funzione array.prototype.every , che fornisce l’utilità per interrompere il ciclo. Vedi esempio qui documentazione di Javascript sulla rete di sviluppatori Mozilla

Accetto con @bobince, upvoted.

Inoltre, FYI:

Prototype.js ha qualcosa per questo scopo:

  

$break verrà catturato e gestito da Prototype.js internamente, interrompendo il ciclo “ciascuno” ma non generando errori esterni.

Vedi API Prototype.JS per i dettagli.

jQuery ha anche un modo, è sufficiente restituire false nel gestore per interrompere il ciclo in anticipo:

  

Vedi API jQuery per i dettagli.

Questo non è il più efficiente, dal momento che continua a ciclizzare tutti gli elementi, ma ho pensato che valesse la pena considerare il molto semplice:

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

puoi seguire il codice qui sotto che funziona per me:

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

Lo conosco non nel modo giusto Non è rompere il ciclo. È una Jugad

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

Preferisco usare for in

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

Se è necessario interrompere in base al valore degli elementi già presenti nell’array come nel tuo caso (ovvero se la condizione di interruzione non dipende dalla variabile di runtime che potrebbe cambiare dopo che gli array hanno assegnato i suoi valori di elemento) potresti utilizzare anche la combinazione di slice () e indexOf () come segue.

Se è necessario interrompere quando forEach raggiunge ‘Apple’ è ansible utilizzare

 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 }); 

Come affermato in W3Schools.com, il metodo slice () restituisce gli elementi selezionati in una matrice, come un nuovo object array. La matrice originale non sarà cambiata.

Guardalo in JSFiddle

Spero che aiuti qualcuno.

prova con “trova”:

 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" } 

La risposta corretta dipende dal motivo per cui vuoi farlo.

Se quello che vuoi è: “come un modo pulito e conciso di uscire da forEach() più ansible dato che l’ break non è consentita” allora puoi ridefinire Array.forEach () per farti fare questo:

 [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) }) 

Ecco l’override, nota che forEach() normalmente passa due parametri: l’object attualmente iterato e l’indice. Stiamo aggiungendo un terzo:

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

Puoi usare qualunque nome ti piaccia (tranne break , o qualsiasi altra parola chiave riservata, non c'è fortuna!)

(Su un progetto reale dovresti andare con una delle risposte super upvoted. Sto solo aggiungendo questo perché alcune persone potrebbero trovare il concetto utile in altre applicazioni).

 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);