Kurzschluss Array.forJeder wie Call Break

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

Wie kann ich dies mit der neuen forEachMethode in JavaScript tun ? Ich habe versucht return;, return false;und break. breakstürzt ab und returnmacht nichts anderes als die Iteration fortzusetzen.

Scott Klarenbach
quelle
6
Es ist erwähnenswert, dass returndie Iteration zwar fortgesetzt wird, jedoch der nachfolgende Code im Block übersprungen wird. Nehmen Sie zum Beispiel diesen Code: [1,2,3].forEach(function(el) { if(el === 2) { console.log(`Match on 2!`); return; } console.log(el); });.Der console.log(el);wird übersprungen, wenn 2 übereinstimmt.
Shane
5
TL; DR: Ich werde den meisten von Ihnen viel Zeit sparen. Ich habe in letzter Zeit viel JS verwendet. Die Antwort (von 28 ...), die Sie wahrscheinlich suchen, ist diese: stackoverflow.com/a/32101207/1599699
Andrew

Antworten:

2141

Es gibt keine eingebaute Fähigkeit zu breakin forEach. Um die Ausführung zu unterbrechen, müssten Sie eine Ausnahme auslösen. z.B.

var BreakException = {};

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

JavaScript-Ausnahmen sind nicht besonders hübsch. Eine herkömmliche forSchleife ist möglicherweise besser geeignet, wenn Sie sie wirklich benötigen break.

Verwenden Array#some

Verwenden Sie stattdessen Array#some:

[1, 2, 3].some(function(el) {
  console.log(el);
  return el === 2;
});

Dies funktioniert, weil somezurückgegeben wird true, sobald einer der in Array-Reihenfolge ausgeführten Rückrufe zurückkehrt trueund die Ausführung des Restes kurzschließt.

some, es ist invers every(was bei a stoppt return false) und forEachsind alle ECMAScript Fifth Edition-Methoden, die zu den Array.prototypeOn-Browsern hinzugefügt werden müssen, in denen sie fehlen.

Bobince
quelle
110
Dies ist weder lesbarer noch performanter als die Verwendung einer normalen for-Schleife. Die Antwort sollte lauten: "In diesem Fall nicht für jeden verwenden" -1
BT
37
Ich denke, "einige" sind hier in Ordnung, warum nicht die frühe Exit-Optimierung verwenden
Chrismarx
28
Vielen Dank für Ihre Aufmerksamkeit someund everydies sollte in der Antwort ganz oben stehen. Ich kann nicht verstehen, warum die Leute denken, dass es weniger lesbar ist. Es ist einfach großartig!
Karl Adler
9
Die Verwendung von Array#someist wirklich nett. Erstens ist es mit den meisten Browsern kompatibel, einschließlich IE9 und Firefox 1.5, und funktioniert auch sehr gut. Mein beispielhafter Anwendungsfall besteht darin, den Index in einem Array von Bereichen [a, b] zu finden, in denen eine Zahl zwischen einem unteren und einem oberen Grenzpaar liegt. Testen Sie und geben Sie true zurück, wenn es gefunden wird. for..ofwäre die nächstbeste Lösung allerdings nur für neuere Browser.
Sojimaxi
95
Die Ausnahmebehandlung sollte NIEMALS als Kontrollfluss verwendet werden. ZEITRAUM.
Frank
479

In ECMAScript2015 (auch bekannt als ES6) gibt es jetzt eine noch bessere Möglichkeit, dies mit der neuen for of-Schleife zu tun . Beispielsweise druckt dieser Code die Array-Elemente nach der Nummer 5 nicht:

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

Aus den Dokumenten:

Sowohl für ... in als auch für ... von Aussagen iterieren über etwas. Der Hauptunterschied zwischen ihnen besteht darin, worüber sie iterieren. Die for ... in- Anweisung durchläuft die aufzählbaren Eigenschaften eines Objekts in der ursprünglichen Einfügereihenfolge. Die for ... of- Anweisung iteriert über Daten, über die das iterierbare Objekt iteriert.

Benötigen Sie den Index in der Iteration? Sie können verwenden Array.entries():

for (const [index, el] of arr.entries()) {
  if ( index === 5 ) break;
}
canac
quelle
4
@superhero Sie können den Index des Elements in einer for ... of-Schleife abrufen, die Sie nur verwenden müssen entries. for (const [index, element] von someArray.entries ()) {// ...}
blackxored
Wird nicht empfohlen, nicht für ... in Arrays zu verwenden?
Schehata
4
@emostafa Sie sind richtig über für in Schleifen nicht für Arrays empfohlen werden, aber dies ist Ansatz nutzt eigentlich ein für von Schleife.
Canac
Dies ist "für", und dies ist eine wirklich saubere Lösung ... aber dies ist auch eine ES6-Funktion. Beachten Sie also, dass dies nur funktioniert, wenn Ihre Umgebung für ES6 eingerichtet ist.
Chad
Ich benutze diese Lösung häufig und auch für Objekte. Mit Objekten können Sie Object.entries(myObject)es genau so verwenden und dann verwenden, wie Sie es for..infür das Array verwenden. Beachten Sie, dass JS-Arrays im Grunde genommen Objekte unter der Haube sind: blog.niftysnippets.org/2011/01/myth-of-arrays.html
Andrew
204

Sie können jede Methode verwenden:

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

ES6

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

für die Unterstützung alter Browser:

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

Weitere Details hier .

Valdemar_Rudolfovich
quelle
10
Schön und sauber in ES6 jetzt -[1,2,3].every( el => el !== 1 )
Metame
1
@Valdemar, aber every garantiert, dass Anrufe nacheinander getätigt werden?
Pacerier
4
@Pacerier, Sie können den Algorithmus in der ES6-Spezifikation sehen, dass der Index kbei 0 beginnt und um 1 erhöht wird: http://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.every
XP1
@ XP1, Müssen alle Implementierer dies so tun?
Pacerier
1
@ Pacerier, ja, die meisten gängigen Implementierungen funktionieren ordnungsgemäß. Wenn Sie sich Gedanken über eingebettete Implementierungen machen, ist dies normalerweise Opera oder Webkit. Methode jeden Aufruf callbackfn einmal für jedes im Array vorhandene Element in aufsteigender Reihenfolge , bis es eines findet, bei dem callbackfn false zurückgibt. Schauen Sie sich auch Schritt 7 an. Sei k 0. und 8.e Erhöhen Sie k um 1.
Valdemar_Rudolfovich
78

Zitat aus der MDN-Dokumentation vonArray.prototype.forEach() :

Es gibt keineforEach() andere Möglichkeit, eine Schleife anzuhalten oder zu unterbrechen, als eine Ausnahme auszulösen. Wenn Sie ein solches Verhalten benötigen, ist die .forEach()Methode das falsche Werkzeug . Verwenden Sie stattdessen eine einfache Schleife. Wenn Sie die Array-Elemente auf ein Prädikat testen und einen booleschen Rückgabewert benötigen, können Sie verwendenevery() oder some()stattdessen verwenden.

Verwenden Sie Array.prototype.some()stattdessen für Ihren Code (in der Frage), wie von @bobince vorgeschlagen . Es passt sehr gut zu Ihrem Anwendungsfall.

Array.prototype.some()führt die Rückruffunktion einmal für jedes im Array vorhandene Element aus, bis es eines findet, bei dem der Rückruf einen wahrheitsgemäßen Wert zurückgibt (einen Wert, der wahr wird, wenn er in a konvertiert wird Boolean). Wenn ein solches Element gefunden wird, wird some()sofort true zurückgegeben. Andernfalls wird some()false zurückgegeben. Der Rückruf wird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen wurden. Es wird nicht für Indizes aufgerufen, die gelöscht wurden oder denen nie Werte zugewiesen wurden.

Rahul Desai
quelle
1
Dies ist die richtige Antwort. 'some' macht genau das, was ein foreach / break machen würde. Es wird eine Schleife ausgeführt, bis die Iteration n = true ist.
Antony Booth
74

Leider ist es in diesem Fall viel besser, wenn Sie nicht verwenden forEach. Verwenden Sie stattdessen eine reguläre forSchleife, die jetzt genau so funktioniert, wie Sie es erwarten würden.

var array = [1, 2, 3];
for (var i = 0; i < array.length; i++) {
  if (array[i] === 1){
    break;
  }
}
Weston Ganger
quelle
27
Es schockiert mich, dass die höchste Abstimmung die schlechteste Implementierung ist, verglichen mit der höheren Leistung, dem geringeren Code und der besseren Lesbarkeit dieser richtigen Antwort. Ausnahme auslösen ... wirklich? Ist die traditionelle for-Schleife einfach nicht genug?
GDBJ
2
@gdbj Ich stimme Ihrer Aussage zu und habe diese Methode verwendet, aber was mich wirklich schockiert, ist, dass es keine Möglichkeit gibt, einen forEach ohne diese Hacks zu beenden. Das ist schlechtes Design.
ScottN
28

Erwägen Sie die Verwendung jqueryder eachMethode von ', da sie die Rückgabe von false innerhalb der Rückruffunktion ermöglicht:

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

Lodash-Bibliotheken bieten auch takeWhileMethoden, die mit map / redu / fold etc verkettet werden können:

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');
// => []
vittore
quelle
1
Guter Grund, jQuery zu verwenden. forJedes in nativem Javascript fehlt noch.
Alex Grande
3
@AlexGrande jQuery's forEach und JavaScript's forEach sind nicht kompatibel.
Björn
10
JavaScript wird an vielen Stellen verwendet, an denen jQuery keine Option ist.
JBRWilkinson
18

Wenn Sie den Vorschlag von Dean Edward verwenden und den StopIteration-Fehler auslösen möchten, um aus der Schleife auszubrechen, ohne den Fehler abfangen zu müssen, können Sie die folgende Funktion verwenden ( ursprünglich von hier ):

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

Mit dem obigen Code können Sie Code wie den folgenden ausführen, ohne Ihre eigenen Try-Catch-Klauseln ausführen zu müssen:

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

Beachten Sie, dass dadurch die Funktion Array.prototype.forEach nur aktualisiert wird, wenn sie bereits vorhanden ist. Wenn es noch nicht vorhanden ist, wird es nicht geändert.

Chris West
quelle
11

Kurze Antwort: Verwenden Sie for...breakdiese Option oder ändern Sie Ihren Code, um ein Brechen zu vermeiden forEach. Nicht verwenden .some()oder .every()emulieren for...break. Schreiben Sie Ihren Code neu, um for...breakSchleifen zu vermeiden , oder verwenden Sie ihn for...break. Jedes Mal, wenn Sie diese Methoden als for...breakAlternative verwenden, tötet Gott Kätzchen.

Lange Antwort:

.some()und .every()beide geben den booleanWert .some()zurück, truewenn ein Element zurückgegeben wird, für das die übergebene Funktion zurückgegeben wurde true, und jedes, falsewenn ein Element zurückgegeben wird, für das die übergebene Funktion zurückgegeben wurde false. Das ist es, was diese Funktionen bedeuten. Die Verwendung von Funktionen für das, was sie nicht bedeuten, ist viel schlimmer als die Verwendung von Tabellen für das Layout anstelle von CSS, da dies jeden frustriert, der Ihren Code liest.

Die einzige Möglichkeit, diese Methoden als for...breakAlternative zu verwenden, besteht darin, Nebenwirkungen zu verursachen (einige Variablen außerhalb der .some()Rückruffunktion zu ändern ), und dies unterscheidet sich nicht wesentlich von for...break.

Die Verwendung von .some()oder .every()als for...breakLoop-Alternative ist also nicht frei von Nebenwirkungen. Dies ist dann nicht viel sauberer for...break. Dies ist frustrierend und daher nicht besser.

Sie können Ihren Code jederzeit neu schreiben, sodass keine Notwendigkeit besteht for...break. Sie können das Array mit filtern .filter(), das Array mit .slice()usw. teilen und dann .forEach()oder .map()für diesen Teil des Arrays verwenden.

Max
quelle
Die Verwendung von .filter ist tatsächlich die geeignete Lösung für viele Anwendungsfälle zum Brechen.
TKoL
Was ist mit Leistung? Wird der Filter die Leistung nicht beeinträchtigen, wenn er häufig verwendet wird?
Tfrascaroli
Ja, der Filterarray-Prototyp kann schwer werden. Ich liebe es, aber es könnte die Leistung beeinträchtigen, wenn es überbeansprucht wird.
Chad
@tfrascaroli benutze for...breakSchleife, wenn du Leistung brauchst.forSchleife ist die performante Iteration als Werkzeug .forEach(), .any(), .map(), .filter()usw.
Max
6

Dies ist nur etwas, das ich mir ausgedacht habe, um das Problem zu lösen ... Ich bin mir ziemlich sicher, dass es das Problem behebt, das der ursprüngliche Fragesteller hatte:

Array.prototype.each = function(callback){
    if(!callback) return false;
    for(var i=0; i<this.length; i++){
        if(callback(this[i], i) == false) break;
    }
};

Und dann würden Sie es nennen, indem Sie verwenden:

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

Die Rückgabe von false innerhalb der Rückruffunktion führt zu einer Unterbrechung. Lassen Sie mich wissen, wenn das nicht funktioniert.

Tennisagent
quelle
1
=== falseMöglicherweise ist es besser == false, wenn Sie nicht explizit true (oder einen truey-Wert) zurückgeben müssen, um die Schleife fortzusetzen, damit ein Steuerpfad keinen Wert zurückgibt und die Schleife unerwartet unterbrochen wird.
Jake
6

Ein anderes Konzept, das ich mir ausgedacht habe:

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

c24w
quelle
Die Syntax ähnelt [NSArray enumerateObjectsUsingBlock]. Danke!
Chrstph SLN
@Drenai die Signatur ist analog zum Native Array.prototype.forEach(). forund breakexistierte lange bevor diese Frage gestellt wurde; Das OP suchte nach diesem Verhalten, indem es funktionaler war forEach.
c24w
@Drenai hat jetzt ihren Kommentar gelöscht (aber die Abwertung hinterlassen), in dem erwähnt wurde, dass die Signatur dieser Lösung schwer zu merken und unnötig ist, wenn Sie das Problem mit for...inund lösen können break.
c24w
5

Diese Lösung wurde auf einer anderen Site gefunden. Sie können forEach in ein Try / Catch-Szenario einschließen.

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

Weitere Details hier: http://dean.edwards.name/weblog/2006/07/enum/

RussellUresti
quelle
2
Verwenden Sie keine Ausnahmen als Kontrollflussanweisungen. Verwenden Sie es, um unerwartete Ergebnisse zu verarbeiten.
Max
5
var array = [1,2,3,4];

for(var item of array){
    console.log(item);
    if(item == 2){
       break;
    }
}
Surojit Paul
quelle
4

Wenn Sie nach der Iteration nicht auf Ihr Array zugreifen müssen, können Sie aussteigen, indem Sie die Länge des Arrays auf 0 setzen. Wenn Sie es nach Ihrer Iteration noch benötigen, können Sie es mit Slice klonen.

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

Oder mit einem Klon:

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

Das ist eine weitaus bessere Lösung, als zufällige Fehler in Ihren Code zu werfen.

3rdEden
quelle
gut gemacht :) aber wenn es einige Aktionen sind nach Zuweisung array.lengthan 0sie in der aktuellen Iteration anwenden wird, ist es so wahrscheinlich manchmal besser zu Einsatz returnnach einer solchen Zuweisung
zhibirc
4

Dies ist eine for-Schleife, behält jedoch die Objektreferenz in der Schleife wie forEach () bei, aber Sie können ausbrechen.

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

Wie bereits erwähnt, können Sie nicht brechen .forEach() .

Hier ist eine etwas modernere Methode, um mit ES6-Iteratoren einen Foreach durchzuführen. Ermöglicht den direkten Zugriff auf index/ valuebeim Iterieren.

const array = ['one', 'two', 'three'];

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

Ausgabe:

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

Links

Alex
quelle
3

Noch ein Ansatz

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

Ich benutze nullhack für diesen Zweck, es versucht, auf die Eigenschaft von zuzugreifen null, was ein Fehler ist:

try {
  [1,2,3,4,5]
  .forEach(
    function ( val, idx, arr ) {
      if ( val == 3 ) null.NULLBREAK;
    }
  );
} catch (e) {
  // e <=> TypeError: null has no properties
}
//
öffentliche Außerkraftsetzung
quelle
1
Warum nicht einfach throw BREAK?
Bergi
1

Wenn du deine behalten willst forEach Syntax diese Weise effizient halten (obwohl sie nicht so gut ist wie eine reguläre for-Schleife). Suchen Sie sofort nach einer Variablen, die weiß, ob Sie aus der Schleife ausbrechen möchten.

In diesem Beispiel wird eine anonyme Funktion zum Erstellen eines Funktionsbereichs verwendet, um den forEachSie die erledigten Informationen speichern müssen .

(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;
        }
    });
})();
<div id="printed-result"></div>

Meine zwei Cent.

Justus Romijn
quelle
1

Ich weiß es nicht richtig. Es ist nicht die Schleife zu brechen. Es ist ein Jugad

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

Durgpal Singh
quelle
0

Stimmen Sie mit @bobince überein, gestimmt.

Auch zu Ihrer Information:

Prototype.js hat etwas für diesen Zweck:

<script type="text/javascript">
  $$('a').each(function(el, idx) {
    if ( /* break condition */ ) throw $break;
    // do something
  });
</script>

$break wird von Prototype.js intern abgefangen und verarbeitet, wodurch der "jeder" Zyklus unterbrochen wird, jedoch keine externen Fehler generiert werden.

Weitere Informationen finden Sie unter Prototype.JS-API .

jQuery hat auch eine Möglichkeit, einfach false im Handler zurückzugeben, um die Schleife frühzeitig zu unterbrechen:

<script type="text/javascript">
  jQuery('a').each( function(idx) {
    if ( /* break condition */ ) return false;
    // do something

  });
</script>

Weitere Informationen finden Sie unter jQuery-API .

Dmitri Sologoubenko
quelle
0

Dies ist nicht die effizienteste, da Sie immer noch alle Elemente durchlaufen, aber ich dachte, es könnte sich lohnen, das sehr einfache zu betrachten:

let keepGoing = true;
things.forEach( (thing) => {
  if (noMore) keepGoing = false;
  if (keepGoing) {
     // do things with thing
  }
});
Märtyrer
quelle
continueist ein Schlüsselwort, Ihr Code ist ein Syntaxfehler.
Bergi
3
Da Sie ohnehin ES6 verwenden, sollten Sie einfach zu einer for ofSchleife wechseln und break;von dieser wie gewohnt.
Bergi
behoben und wahr - aber es wurde hauptsächlich es6 der Kürze
halber verwendet
0

Sie können dem folgenden Code folgen, der für mich funktioniert:

 var     loopStop = false;
YOUR_ARRAY.forEach(function loop(){
    if(loopStop){ return; }
    if(condition){ loopStop = true; }
});
BERGUIGA Mohamed Amine
quelle
Warum die -1? Es ist nicht hässlicher als eine Ausnahme zu erwischen, das ist meiner Meinung nach ein größerer Hack.
Byron Whitlock
0

Ich benutze lieber for in

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

for infunktioniert ähnlich forEach, und Sie können die Return-to-Exit-Funktion hinzufügen. Bessere Leistung auch.

Jorge Alberto
quelle
0

Wenn Sie wie in Ihrem Fall basierend auf dem Wert von Elementen, die sich bereits in Ihrem Array befinden, eine Unterbrechung vornehmen müssen (dh wenn die Unterbrechungsbedingung nicht von der Laufzeitvariablen abhängt, die sich ändern kann, nachdem dem Array seine Elementwerte zugewiesen wurden), können Sie auch eine Kombination verwenden von Slice () und IndexOf () wie folgt.

Wenn Sie brechen müssen, wenn forEach 'Apple' erreicht, können Sie verwenden

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

Wie in W3Schools.com angegeben, gibt die Slice () -Methode die ausgewählten Elemente in einem Array als neues Array-Objekt zurück. Das ursprüngliche Array wird nicht geändert.

Sehen Sie es in JSFiddle

Hoffe es hilft jemandem.

Ula
quelle
0

Sie können eine Variante erstellen von forEachdem ermöglicht break, continue, returnund sogar async/ await: (Beispiel in Typoskript geschrieben)

export type LoopControlOp = "break" | "continue" | ["return", any];
export type LoopFunc<T> = (value: T, index: number, array: T[])=>LoopControlOp;

Array.prototype.ForEach = function ForEach<T>(this: T[], func: LoopFunc<T>) {
    for (let i = 0; i < this.length; i++) {
        const controlOp = func(this[i], i, this);
        if (controlOp == "break") break;
        if (controlOp == "continue") continue;
        if (controlOp instanceof Array) return controlOp[1];
    }
};

// this variant lets you use async/await in the loop-func, with the loop "awaiting" for each entry
Array.prototype.ForEachAsync = async function ForEachAsync<T>(this: T[], func: LoopFunc<T>) {
    for (let i = 0; i < this.length; i++) {
        const controlOp = await func(this[i], i, this);
        if (controlOp == "break") break;
        if (controlOp == "continue") continue;
        if (controlOp instanceof Array) return controlOp[1];
    }
};

Verwendungszweck:

function GetCoffee() {
    const cancelReason = peopleOnStreet.ForEach((person, index)=> {
        if (index == 0) return "continue";
        if (person.type == "friend") return "break";
        if (person.type == "boss") return ["return", "nevermind"];
    });
    if (cancelReason) console.log("Coffee canceled because: " + cancelReason);
}
Venryx
quelle
-1

versuchen Sie es mit "find":

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" }
GigolNet Guigolachvili
quelle
-1

Ja, es ist möglich, fortzufahren und eine forEach-Schleife zu verlassen.

Um fortzufahren, können Sie return verwenden. Die Schleife wird fortgesetzt, aber die aktuelle Funktion wird beendet.

Um die Schleife zu verlassen, können Sie den dritten Parameter auf die Länge 0 und das leere Array setzen. Die Schleife wird nicht fortgesetzt, die aktuelle Funktion jedoch, sodass Sie "return" zum Beenden verwenden können, wie z. B. das Beenden in einer normalen for-Schleife ...

Diese:

[1,2,3,4,5,6,7,8,9,10].forEach((a,b,c) => {
    console.log(a);
    if(b == 2){return;}
    if(b == 4){c.length = 0;return;}
    console.log("next...",b);
});

wird dies drucken:

1
next... 0
2
next... 1
3
4
next... 3
5
Luis Marin
quelle
-2

Vorher ist mein Code unten

 this.state.itemsDataSource.forEach((item: any) => {
                if (!item.isByPass && (item.invoiceDate == null || item.invoiceNumber == 0)) {

                    return false;
                }
            });

Ich habe nach unten gewechselt, es wurde behoben.

 for (var i = 0; i < this.state.itemsDataSource.length; i++) {
                var item = this.state.itemsDataSource[i];
                if (!item.isByPass && (item.invoiceDate == null || item.invoiceNumber == 0)) {

                    return false;
                }
            }
Metin Atalay
quelle