Ich habe danach gesucht, aber ich habe gesucht forEach und nicht nur for. wie gesagt, in c # war es ein bisschen anders, und das hat mich verwirrt :)
Dante1986
6
ECMAScript 6 enthält möglicherweise das Konstrukt "for ... of". Siehe für ... von (MDN) für weitere Informationen. Sie können es bereits mit den neuesten Firefox-Versionen ausprobieren.
Im Gegensatz dazu in Python ist es effiziente Funktionen zu verwenden , als zu verwenden traditioneller for - Schleifen. ( Man bedenke , dass i < lenund i++kann durch den Motor durchgeführt werden, anstatt durch den Interpreter.)
joeytwiddle
Antworten:
7021
TL; DR
Verwenden for-inSie es nur, wenn Sie es mit Schutzmaßnahmen verwenden oder zumindest wissen, warum es Sie beißen könnte.
Aber es gibt noch viel mehr zu entdecken, weiterzulesen ...
JavaScript verfügt über eine leistungsstarke Semantik zum Durchlaufen von Arrays und Array-ähnlichen Objekten. Ich habe die Antwort in zwei Teile geteilt: Optionen für echte Arrays und Optionen für Dinge, die nur Array- ähnlich sind , wie das argumentsObjekt, andere iterierbare Objekte (ES2015 +), DOM-Sammlungen und so weiter.
Ich werde schnell beachten Sie, dass Sie die ES2015 - Optionen können nun auch auf ES5 - Motoren, von transpiling ES2015 bis ES5. Suchen Sie nach "ES2015 transpiling" / "ES6 transpiling" für mehr ...
Okay, schauen wir uns unsere Optionen an:
Für tatsächliche Arrays
Sie haben drei Optionen in ECMAScript 5 ("ES5"), der derzeit am weitesten verbreiteten Version, und zwei weitere in ECMAScript 2015 ("ES2015", "ES6"):
Verwendung forEachund verwandte (ES5 +)
Verwenden Sie eine einfache forSchleife
verwenden Sie for-inrichtig
Verwenden for-of(implizit einen Iterator verwenden) (ES2015 +)
Verwenden Sie explizit einen Iterator (ES2015 +)
Einzelheiten:
1. Verwenden forEachund verwandt
In jeder vage modernen Umgebung (also nicht in IE8), in der Sie Zugriff auf die Arrayvon ES5 hinzugefügten Funktionen haben (direkt oder mithilfe von Polyfills), können Sie forEach( spec| MDN) verwenden:
var a =["a","b","c"];
a.forEach(function(entry){
console.log(entry);});
forEachAkzeptiert eine Rückruffunktion und optional einen Wert, der thisbeim Aufrufen dieses Rückrufs verwendet werden soll (oben nicht verwendet). Der Rückruf wird für jeden Eintrag im Array aufgerufen, um nicht vorhandene Einträge in dünn besetzten Arrays zu überspringen. Obwohl ich oben nur ein Argument verwendet habe, wird der Rückruf mit drei aufgerufen: Der Wert jedes Eintrags, der Index dieses Eintrags und ein Verweis auf das Array, über das Sie iterieren (falls Ihre Funktion es noch nicht zur Hand hat ).
Sofern Sie nicht veraltete Browser wie IE8 unterstützen (NetApps weist zum Zeitpunkt dieses Schreibens im September 2016 einen Marktanteil von etwas mehr als 4% auf), können Sie diese forEachproblemlos auf einer Allzweck-Webseite ohne Shim verwenden. Wenn Sie veraltete Browser unterstützen müssen, ist das Shimmen / Polyfilling forEacheinfach (suchen Sie nach "es5 shim" für mehrere Optionen).
forEach hat den Vorteil, dass Sie keine Indexierungs- und Wertvariablen im enthaltenen Bereich deklarieren müssen, da sie als Argumente für die Iterationsfunktion bereitgestellt werden und sich so gut auf diese Iteration beschränken.
Wenn Sie sich Sorgen über die Laufzeitkosten für einen Funktionsaufruf für jeden Array-Eintrag machen, sollten Sie dies nicht tun. Details .
Darüber hinaus gibt forEaches die Funktion "Schleife durch alle", aber ES5 hat mehrere andere nützliche Funktionen definiert, mit denen Sie sich durch das Array arbeiten und Dinge erledigen können, darunter:
every(stoppt die Schleife, wenn der Rückruf zum ersten Mal zurückkehrt falseoder etwas Falsches)
some(stoppt die Schleife, wenn der Rückruf zum ersten Mal zurückkehrt trueoder etwas Wahres)
filter(Erstellt ein neues Array mit Elementen, bei denen die Filterfunktion zurückgegeben wird, trueund lässt diejenigen weg, bei denen sie zurückgegeben wird. false)
map (Erstellt ein neues Array aus den vom Rückruf zurückgegebenen Werten.)
reduce (Baut einen Wert auf, indem der Rückruf wiederholt aufgerufen wird und vorherige Werte übergeben werden. Einzelheiten finden Sie in der Spezifikation. Nützlich zum Summieren des Inhalts eines Arrays und vieler anderer Dinge.)
reduceRight(wie reduce, funktioniert aber eher in absteigender als in aufsteigender Reihenfolge)
2. Verwenden Sie eine einfache forSchleife
Manchmal sind die alten Wege die besten:
var index;var a =["a","b","c"];for(index =0; index < a.length;++index){
console.log(a[index]);}
Wenn die Länge des Feldes wird nicht während der Schleife ändern, und es ist in leistungskritischen Code (unwahrscheinlich), eine etwas kompliziertere Version die Länge vorne greifen könnte ein seine winzig bisschen schneller:
var index, len;var a =["a","b","c"];for(index =0, len = a.length; index < len;++index){
console.log(a[index]);}
Bei modernen JavaScript-Engines ist es jedoch selten, dass Sie das letzte Stück Saft herausholen müssen.
In ES2015 und höher können Sie Ihre Index- und Wertvariablen lokal für die forSchleife festlegen :
let a =["a","b","c"];for(let index =0; index < a.length;++index){let value = a[index];
console.log(index, value);}//console.log(index); // would cause "ReferenceError: index is not defined"//console.log(value); // would cause "ReferenceError: value is not defined"
let a =["a","b","c"];for(let index =0; index < a.length;++index){let value = a[index];
console.log(index, value);}try{
console.log(index);}catch(e){
console.error(e);// "ReferenceError: index is not defined"}try{
console.log(value);}catch(e){
console.error(e);// "ReferenceError: value is not defined"}
Und wenn Sie dies tun, wird nicht nur, valuesondern auch indexfür jede Schleifeniteration neu erstellt, was bedeutet, dass im Schleifenkörper erstellte Abschlüsse einen Verweis auf das index(und value) enthalten, das für diese bestimmte Iteration erstellt wurde:
let divs = document.querySelectorAll("div");for(let index =0; index < divs.length;++index){
divs[index].addEventListener('click', e =>{
console.log("Index is: "+ index);});}
let divs = document.querySelectorAll("div");for(let index =0; index < divs.length;++index){
divs[index].addEventListener('click', e =>{
console.log("Index is: "+ index);});}
Wenn Sie fünf Divs hatten, erhalten Sie "Index ist: 0", wenn Sie auf den ersten geklickt haben, und "Index ist: 4", wenn Sie auf den letzten geklickt haben. Dies funktioniert nicht , wenn Sie varanstelle von verwenden let.
3. for-inRichtig verwenden
Sie erhalten die Menschen sagen , die Sie zu verwenden for-in, aber das ist nicht das, was for-infür ist . for-inDurchläuft die aufzählbaren Eigenschaften eines Objekts und nicht die Indizes eines Arrays. Die Bestellung ist nicht garantiert , auch nicht in ES2015 (ES6). ES2015 + definiert zwar eine Reihenfolge für Objekteigenschaften (via [[OwnPropertyKeys]], [[Enumerate]]und Dinge, die sie verwenden Object.getOwnPropertyKeys), aber es wurde nicht definiert, for-inwelche Reihenfolge dieser Reihenfolge folgen würde. ES2020 hat es jedoch getan. (Details in dieser anderen Antwort .)
Die einzigen realen Anwendungsfälle für for-inein Array sind:
Sie verwenden Nicht-Elementeigenschaften und möchten diese in die Schleife aufnehmen
Betrachten Sie nur das erste Beispiel: Sie können for-indiese spärlichen Array-Elemente verwenden, wenn Sie geeignete Sicherheitsvorkehrungen treffen:
// `a` is a sparse arrayvar key;var a =[];
a[0]="a";
a[10]="b";
a[10000]="c";for(key in a){if(a.hasOwnProperty(key)&&// These checks are/^0$|^[1-9]\d*$/.test(key)&&// explained
key <=4294967294// below){
console.log(a[key]);}}
Dass das Objekt eine eigene Eigenschaft mit diesem Namen hat (keine, die es von seinem Prototyp erbt), und
Dass der Schlüssel alle Dezimalstellen sind (z. B. normale Zeichenfolgenform, keine wissenschaftliche Notation), und
Dass der Wert des Schlüssels, wenn er zu einer Zahl gezwungen wird, <= 2 ^ 32 - 2 ist (was 4,294,967,294 ist). Woher kommt diese Nummer? Es ist Teil der Definition eines Array-Index in der Spezifikation . Andere Zahlen (Nicht-Ganzzahlen, negative Zahlen, Zahlen größer als 2 ^ 32 - 2) sind keine Array-Indizes. Der Grund, warum es 2 ^ 32 - 2 ist, ist, dass dadurch der größte Indexwert niedriger als 2 ^ 32 - 1 wird , was der maximale Wert ist, den ein Array haben lengthkann. (ZB passt die Länge eines Arrays in eine 32-Bit-Ganzzahl ohne Vorzeichen.) (Wir bitten RobG, in einem Kommentar in meinem Blog-Beitrag darauf hinzuweisen, dass mein vorheriger Test nicht ganz richtig war.)
Das würden Sie natürlich nicht im Inline-Code tun. Sie würden eine Dienstprogrammfunktion schreiben. Vielleicht:
// Utility function for antiquated environments without `forEach`var hasOwn =Object.prototype.hasOwnProperty;var rexNum =/^0$|^[1-9]\d*$/;function sparseEach(array, callback, thisArg){var index;for(var key in array){
index =+key;if(hasOwn.call(a, key)&&
rexNum.test(key)&&
index <=4294967294){
callback.call(thisArg, array[key], index, array);}}}var a =[];
a[5]="five";
a[10]="ten";
a[100000]="one hundred thousand";
a.b ="bee";
sparseEach(a,function(value, index){
console.log("Value at "+ index +" is "+ value);});
Unter der Decke erhält das einen Iterator aus dem Array und durchläuft es, wobei die Werte daraus abgerufen werden. Dies hat nicht das Problem, das bei der Verwendung for-inauftritt, da ein vom Objekt (dem Array) definierter Iterator verwendet wird und Arrays definieren, dass ihre Iteratoren ihre Einträge (nicht ihre Eigenschaften) durchlaufen . Anders als for-inin ES5 ist die Reihenfolge, in der die Einträge besucht werden, die numerische Reihenfolge ihrer Indizes.
5. Verwenden Sie explizit einen Iterator (ES2015 +)
Manchmal möchten Sie möglicherweise einen Iterator explizit verwenden . Sie können das auch tun, obwohl es viel klobiger ist als for-of. Es sieht aus wie das:
const a =["a","b","c"];const it = a.values();let entry;while(!(entry = it.next()).done){
console.log(entry.value);}
Der Iterator ist ein Objekt, das mit der Iteratordefinition in der Spezifikation übereinstimmt. Die nextMethode gibt bei jedem Aufruf ein neues Ergebnisobjekt zurück . Das Ergebnisobjekt hat eine Eigenschaft, donedie uns mitteilt, ob es fertig ist, und eine Eigenschaft valuemit dem Wert für diese Iteration. ( doneist optional, wenn es wäre false, valueist optional, wenn es wäre undefined.)
Die Bedeutung von valuevariiert je nach Iterator. Arrays unterstützen (mindestens) drei Funktionen, die Iteratoren zurückgeben:
values(): Dies ist die, die ich oben verwendet habe. Es gibt einen Iterator , wobei jedes valueder Array - Eintrag für diese Iteration ( "a", "b", und "c"in dem Beispiel weiter oben).
keys(): Gibt einen Iterator zurück, wobei jeder valueder Schlüssel für diese Iteration ist (für unsere aobigen wäre das also "0"dann "1", dann "2").
entries(): Gibt einen Iterator zurück, wobei jedes valueein Array im Formular [key, value]für diese Iteration ist.
Für Array-ähnliche Objekte
Abgesehen von echten Arrays gibt es auch Array-ähnliche Objekte, die eine lengthEigenschaft und Eigenschaften mit numerischen Namen haben: NodeListInstanzen, das argumentsObjekt usw. Wie durchlaufen wir ihren Inhalt?
Verwenden Sie eine der oben genannten Optionen für Arrays
Zumindest einige und möglicherweise die meisten oder sogar alle der oben genannten Array-Ansätze gelten häufig gleich gut für Array-ähnliche Objekte:
Verwendung forEachund verwandte (ES5 +)
Die verschiedenen Funktionen Array.prototypesind "absichtlich generisch" und können normalerweise für Array-ähnliche Objekte über Function#calloder verwendet werden Function#apply. (Siehe die Einschränkung für vom Host bereitgestellte Objekte am Ende dieser Antwort, aber es ist ein seltenes Problem.)
Angenommen , Sie verwenden wollten forEachauf einem Node‚s - childNodesEigenschaft. Du würdest das tun:
Array.prototype.forEach.call(node.childNodes,function(child){// Do something with `child`});
Wenn Sie dies häufig tun, möchten Sie möglicherweise eine Kopie der Funktionsreferenz zur Wiederverwendung in eine Variable aufnehmen, z.
// (This is all presumably in some scoping function)var forEach =Array.prototype.forEach;// Then later...
forEach.call(node.childNodes,function(child){// Do something with `child`});
Verwenden Sie eine einfache forSchleife
Offensichtlich gilt eine einfache forSchleife für Array-ähnliche Objekte.
verwenden Sie for-inrichtig
for-inmit den gleichen Sicherheitsvorkehrungen wie mit einem Array sollte auch mit Array-ähnlichen Objekten funktionieren; Möglicherweise gilt die Einschränkung für vom Host bereitgestellte Objekte unter Nummer 1 oben.
Verwenden for-of(implizit einen Iterator verwenden) (ES2015 +)
for-ofverwendet den vom Objekt bereitgestellten Iterator (falls vorhanden). Dies schließt vom Host bereitgestellte Objekte ein. Beispielsweise wurde die Spezifikation für das NodeListvon querySelectorAllaktualisiert, um die Iteration zu unterstützen. Die Spezifikation für das HTMLCollectionvon getElementsByTagNamewar nicht.
Verwenden Sie explizit einen Iterator (ES2015 +)
Siehe # 4.
Erstellen Sie ein echtes Array
In anderen Fällen möchten Sie möglicherweise ein Array-ähnliches Objekt in ein echtes Array konvertieren. Das ist überraschend einfach:
Verwenden Sie die sliceMethode der Arrays
Wir können die sliceMethode von Arrays verwenden, die wie die anderen oben genannten Methoden "absichtlich generisch" ist und daher mit Array-ähnlichen Objekten wie diesen verwendet werden kann:
var trueArray =Array.prototype.slice.call(arrayLikeObject);
Wenn wir beispielsweise a NodeListin ein echtes Array konvertieren möchten , können wir Folgendes tun:
var divs =Array.prototype.slice.call(document.querySelectorAll("div"));
Weitere Informationen zu vom Host bereitgestellten Objekten finden Sie weiter unten. Beachten Sie insbesondere, dass dies in IE8 und früheren Versionen fehlschlägt, sodass Sie vom Host bereitgestellte Objekte nicht so verwenden können this.
Verwenden Sie die Spread-Syntax ( ...)
Es ist auch möglich, die Spread-Syntax von ES2015 mit JavaScript-Engines zu verwenden, die diese Funktion unterstützen. Wie for-ofdies den verwendet Iterator vom Objekt zur Verfügung gestellt (siehe # 4 im vorherigen Abschnitt):
var trueArray =[...iterableObject];
Wenn wir zum Beispiel a NodeListin ein echtes Array konvertieren möchten , wird dies mit der Spread-Syntax ziemlich prägnant:
var divs =[...document.querySelectorAll("div")];
Verwenden Array.from
Array.from(spec) | (MDN) (ES2015 +, aber leicht polyfüllbar) erstellt ein Array aus einem Array-ähnlichen Objekt, wobei die Einträge optional zuerst über eine Zuordnungsfunktion übergeben werden. Damit:
var divs =Array.from(document.querySelectorAll("div"));
Wenn Sie ein Array der Tag-Namen der Elemente mit einer bestimmten Klasse abrufen möchten, verwenden Sie die Zuordnungsfunktion:
// Arrow function (ES2015):var divs =Array.from(document.querySelectorAll(".some-class"), element => element.tagName);// Standard function (since `Array.from` can be shimmed):var divs =Array.from(document.querySelectorAll(".some-class"),function(element){return element.tagName;});
Vorsichtsmaßnahme für vom Host bereitgestellte Objekte
Wenn Sie Array.prototypeFunktionen mit vom Host bereitgestellten Array-ähnlichen Objekten verwenden (DOM-Listen und andere vom Browser anstelle der JavaScript-Engine bereitgestellte Dinge), müssen Sie sicherstellen, dass Sie in Ihren Zielumgebungen testen, um sicherzustellen, dass sich das vom Host bereitgestellte Objekt ordnungsgemäß verhält . Die meisten verhalten sich (jetzt) richtig , aber es ist wichtig zu testen. Der Grund dafür ist, dass die meisten Array.prototypeMethoden, die Sie wahrscheinlich verwenden möchten, auf dem vom Host bereitgestellten Objekt basieren, das eine ehrliche Antwort auf die abstrakte [[HasProperty]]Operation gibt. Zum jetzigen Zeitpunkt leisten Browser sehr gute Arbeit, aber die 5.1-Spezifikation hat die Möglichkeit berücksichtigt, dass ein vom Host bereitgestelltes Objekt möglicherweise nicht ehrlich ist. Es ist in §8.6.2 , mehrere Absätze unter der großen Tabelle am Anfang dieses Abschnitts), wo es heißt:
Hostobjekte können diese internen Methoden auf jede Art und Weise implementieren, sofern nicht anders angegeben. zum Beispiel ist eine Möglichkeit , dass , [[Get]]und [[Put]]für ein bestimmtes Host - Objekt in der Tat Abruf- und Speichereigenschaftswerte aber [[HasProperty]]immer erzeugt falsch .
(Ich konnte nicht den äquivalent Wortschwall in der ES2015 - Spezifikation finden, aber es ist gesprungen , der Fall noch sein.) Auch hier, wie dies den gemeinsamen Host-bereitgestellt Schreiben Array-ähnliche Objekte in modernen Browsern [ NodeListInstanzen, zum Beispiel] tun Griffes [[HasProperty]]richtig, aber es ist wichtig zu testen.)
Ich möchte auch hinzufügen, dass .forEachnicht effizient gebrochen werden kann. Sie müssen eine Ausnahme auslösen, um die Pause auszuführen.
Pijusn
82
@ Pius: Wenn Sie die Schleife brechen möchten, können Sie verwenden some. (Ich hätte es vorgezogen, auch das Brechen zuzulassen forEach, aber sie haben mich nicht gefragt. ;-))
TJ Crowder
6
@TJCrowder True, obwohl es eher wie eine Problemumgehung aussieht, da es nicht sein Hauptzweck ist.
Pijusn
8
@ user889030: Du brauchst ein ,After k=0, kein ;. Denken Sie daran, Programmierung ist viele Dinge, von denen eines viel Liebe zum Detail ist ... :-)
TJ Crowder
5
@ JimB: Das ist oben behandelt (und lengthist keine Methode). :-)
TJ Crowder
513
Hinweis : Diese Antwort ist hoffnungslos veraltet. Schauen Sie sich für einen moderneren Ansatz die auf einem Array verfügbaren Methoden an . Methoden von Interesse könnten sein:
für jedes
Karte
Filter
Postleitzahl
reduzieren
jeder
etwas
Die Standardmethode zum Iterieren eines Arrays in JavaScript ist eine Vanille- forSchleife:
var length = arr.length,
element =null;for(var i =0; i < length; i++){
element = arr[i];// Do something with element}
Beachten Sie jedoch, dass dieser Ansatz nur dann gut ist, wenn Sie ein dichtes Array haben und jeder Index von einem Element belegt ist. Wenn das Array spärlich ist, können bei diesem Ansatz Leistungsprobleme auftreten, da Sie viele Indizes durchlaufen, die im Array nicht wirklich vorhanden sind. In diesem Fall for .. inkönnte eine Schleife eine bessere Idee sein. Allerdings müssen Sie die entsprechenden Schutzmaßnahmen verwenden , die nur die gewünschten Eigenschaften des Arrays zu gewährleisten (das heißt, die Array - Elemente) beaufschlagt werden, da die for..in-loop auch in älterem Browser aufgelistet werden, oder wenn die zusätzlichen Eigenschaften sind definiert als enumerable.
In ECMAScript 5 gibt es eine forEach-Methode für den Array-Prototyp, die jedoch in älteren Browsern nicht unterstützt wird. Um es konsistent verwenden zu können, müssen Sie entweder über eine Umgebung verfügen, die es unterstützt (z. B. Node.js für serverseitiges JavaScript), oder eine "Polyfill" verwenden. Die Polyfüllung für diese Funktionalität ist jedoch trivial und da sie das Lesen des Codes erleichtert, ist sie eine gute Polyfüllung.
Warum ist for(instance in objArray) eine korrekte Verwendung nicht? es sieht für mich einfacher aus, aber ich höre, dass Sie davon sprechen, dass es nicht die richtige Art der Verwendung ist?
Dante1986
21
Sie können das Inline-Längen-Caching verwenden: für (var i = 0, l = arr.length; i <l; i ++)
Robert Hoffmann
3
Ist das Komma am Ende der ersten Zeile beabsichtigt oder ist es ein Tippfehler (könnte ein Semikolon sein)?
Mohd Abdul Mujib
6
@ wardha-Web Es ist beabsichtigt. Es ermöglicht uns, mehrere Variablen mit einem einzigen varSchlüsselwort zu deklarieren . Wenn wir ein Semikolon verwendet hätten, elementwäre es im globalen Bereich deklariert worden (oder besser gesagt, JSHint hätte uns angeschrien, bevor es die Produktion erreichte).
Ich werde diese Antwort wahrscheinlich am häufigsten verwenden. Es ist nicht die beste Antwort auf die Frage, aber in der Praxis wird es für diejenigen von uns, die jQuery verwenden, die einfachste und am besten geeignete sein. Ich denke, wir sollten alle auch Vanille lernen. Es tut nie weh, Ihr Verständnis zu erweitern.
Mopsyd
47
Nur um der Sache willen: jQuery ist viel langsamer als native Lösungen. Es wird von jQuery empfohlen, natives JavaScript anstelle von jQuery zu verwenden, wann immer dies möglich ist. jsperf.com/browser-diet-jquery-each-vs-for-loop
Kevin Boss
8
Verwenden Sie jQuery nicht, wenn Sie Vanille js
Noe
2
Halten Sie sich an Standard-JS und halten Sie die Bibliotheken von Drittanbietern von der Antwort
fern,
116
Schleife rückwärts
Ich denke, die Umkehrung der Schleife verdient hier eine Erwähnung:
for(var i = array.length; i--;){// process array[i]}
Vorteile:
Sie müssen keine temporäre lenVariable deklarieren oder array.lengthbei jeder Iteration vergleichen, was eine winzige Optimierung sein könnte.
Das Entfernen von Geschwistern aus dem DOM in umgekehrter Reihenfolge ist normalerweise effizienter . (Der Browser muss weniger Elemente in seinen internen Arrays verschieben.)
Wenn Sie das Array während der Schleife am oder nach dem Index i ändern (z. B. wenn Sie ein Element entfernen oder einfügen array[i]), überspringt eine Vorwärtsschleife das Element, das nach links in Position i verschoben wurde , oder verarbeitet das i- te Element erneut nach rechts verschoben. In einem traditionellen for - Schleife, Sie könnten aktualisieren i zum nächsten Punkt zu Punkt , dass Bedürfnisse der Verarbeitung - 1, sondern einfach die Umkehrung der Richtung der Iteration ist oft eine einfachere und elegantere Lösung .
In ähnlicher Weise kann die umgekehrte Verarbeitung beim Ändern oder Entfernen verschachtelter DOM-Elemente Fehler umgehen . Ziehen Sie beispielsweise in Betracht, das innerHTML eines übergeordneten Knotens zu ändern, bevor Sie dessen untergeordnete Knoten behandeln. Wenn der untergeordnete Knoten erreicht ist, wird er vom DOM getrennt und durch ein neu erstelltes untergeordnetes Element ersetzt, als das innerHTML des übergeordneten Knotens geschrieben wurde.
Es ist kürzer zu tippen und zu lesen als einige der anderen verfügbaren Optionen. Obwohl es gegen forEach()und gegen ES6 verliert for ... of.
Nachteile:
Es verarbeitet die Artikel in umgekehrter Reihenfolge. Wenn Sie aus den Ergebnissen ein neues Array erstellt oder Dinge auf dem Bildschirm gedruckt haben, wird die Ausgabe natürlich in Bezug auf die ursprüngliche Reihenfolge umgekehrt .
Das wiederholte Einfügen von Geschwistern als erstes Kind in das DOM, um die Reihenfolge beizubehalten, ist weniger effizient . (Der Browser müsste die Dinge immer wieder nach rechts verschieben.) Um DOM-Knoten effizient und in der richtigen Reihenfolge zu erstellen, müssen Sie nur eine Vorwärtsschleife ausführen und wie gewohnt anhängen (und auch ein "Dokumentfragment" verwenden).
Die umgekehrte Schleife ist für Nachwuchsentwickler verwirrend . (Abhängig von Ihrem Ausblick können Sie dies als Vorteil betrachten.)
Soll ich es immer benutzen?
Einige Entwickler verwenden standardmäßig die umgekehrte for-Schleife , es sei denn, es gibt einen guten Grund, eine Vorwärtsschleife durchzuführen.
Obwohl die Leistungssteigerungen normalerweise unbedeutend sind, schreit es:
"Mach das einfach mit jedem Artikel in der Liste, mir ist die Bestellung egal!"
In der Praxis ist dies jedoch kein verlässlicher Hinweis auf die Absicht, da es nicht von den Gelegenheiten zu unterscheiden ist, in denen Sie sich um die Reihenfolge kümmern und wirklich eine umgekehrte Schleife durchführen müssen. Tatsächlich wäre also ein anderes Konstrukt erforderlich, um die Absicht "egal" genau auszudrücken, was derzeit in den meisten Sprachen, einschließlich ECMAScript, nicht verfügbar ist, aber beispielsweise aufgerufen werden könnte forEachUnordered().
Wenn die Reihenfolge keine Rolle spielt und die Effizienz ein Problem darstellt (in der innersten Schleife eines Spiels oder einer Animations-Engine), kann es akzeptabel sein, die umgekehrte for-Schleife als Ausgangsmuster zu verwenden. Denken Sie daran, dass eine umgekehrte for-Schleife im vorhandenen Code nicht unbedingt bedeutet, dass die Reihenfolge irrelevant ist!
Es war besser, forEach () zu verwenden
Im Allgemeinen habe ich für Code auf höherer Ebene, bei dem Klarheit und Sicherheit eine größere Array::forEachRolle spielen , zuvor empfohlen, als Standardmuster für Schleifen zu verwenden (obwohl ich heutzutage die Verwendung bevorzuge for..of). Gründe, forEacheine Rückwärtsschleife vorzuziehen , sind:
Es ist klarer zu lesen.
Es zeigt an, dass ich nicht innerhalb des Blocks verschoben werde (was immer eine mögliche Überraschung ist, die sich in langen forund whileSchleifen versteckt ).
Es gibt Ihnen einen freien Spielraum für Schließungen.
Es reduziert das Auslaufen lokaler Variablen und die versehentliche Kollision mit (und die Mutation von) äußeren Variablen.
Wenn Sie dann die umgekehrte for-Schleife in Ihrem Code sehen, ist dies ein Hinweis darauf, dass sie aus einem guten Grund umgekehrt ist (möglicherweise einer der oben beschriebenen Gründe). Wenn Sie eine herkömmliche Forward-for-Schleife sehen, kann dies darauf hinweisen, dass eine Verschiebung stattfinden kann.
(Wenn die Diskussion der Absicht für Sie keinen Sinn ergibt, können Sie und Ihr Code davon profitieren, Crockfords Vortrag über Programmierstil und Ihr Gehirn zu sehen .)
Es ist jetzt noch besser für ... zu verwenden!
Es gibt eine Debatte darüber, ob for..ofoder forEach()vorzuziehen sind:
Für eine maximale Browserunterstützung ist for..ofeine Polyfüllung für Iteratoren erforderlich , wodurch die Ausführung Ihrer App etwas langsamer und das Herunterladen etwas größer wird.
Persönlich neige ich dazu, das zu verwenden, was am einfachsten zu lesen ist, es sei denn, Leistung oder Minimierung sind zu einem Hauptanliegen geworden. Daher bevorzuge ich heutzutage die Verwendung for..ofanstelle von forEach(), aber ich werde immer mapoder filteroder findoder somewenn zutreffend verwenden. (Für meine Kollegen benutze ich selten reduce.)
Wie funktioniert es?
for(var i =0; i < array.length; i++){...}// Forwardsfor(var i = array.length; i--;){...}// Reverse
Sie werden feststellen, dass dies i--der mittlere Satz ist (wo wir normalerweise einen Vergleich sehen) und der letzte Satz leer ist (wo wir normalerweise sehen i++). Das heißt, das i--wird auch als Voraussetzung für die Fortsetzung verwendet. Entscheidend ist, dass es vor jeder Iteration ausgeführt und überprüft wird.
Wie kann es beginnen, array.lengthohne zu explodieren?
Da i--läuft vor jeder Iteration bei der ersten Iteration werden wir tatsächlich das Element zugreifen bei array.length - 1denen Probleme mit vermeidet Array-out-of-boundsundefined Artikeln.
Warum hört es nicht auf, vor Index 0 zu iterieren?
Die Schleife i--hört auf zu iterieren, wenn die Bedingung einen Falsey-Wert ergibt (wenn sie 0 ergibt).
Der Trick ist, dass im Gegensatz dazu --ider nachfolgende i--Operator dekrementiert, iaber den Wert vor dem Dekrement liefert . Ihre Konsole kann dies demonstrieren:
> var i = 5; [i, i--, i];
[5, 5, 4]
Bei der letzten Iteration war ich zuvor 1 und der i--Ausdruck ändert ihn in 0 , ergibt aber tatsächlich 1 (wahr), und so besteht die Bedingung. Bei der nächsten Iteration i--ändert sich i auf -1 , ergibt jedoch 0 (Falsey), wodurch die Ausführung sofort aus dem unteren Bereich der Schleife herausfällt.
In der traditionellen Forwards for-Schleife i++und ++isind austauschbar (wie Douglas Crockford betont). Umgekehrt müssen wir jedoch bei der umgekehrten for-Schleife bleiben, da unser Dekrement auch unser Bedingungsausdruck ist, i--wenn wir das Element bei Index 0 verarbeiten möchten.
Wissenswertes
Einige Leute zeichnen gerne einen kleinen Pfeil in die umgekehrte forSchleife und beenden mit einem Augenzwinkern:
for(var i = array.length; i -->0;){
Dank geht an WYL, weil er mir die Vorteile und Schrecken der umgekehrten for-Schleife gezeigt hat.
Ich habe vergessen, die Benchmarks hinzuzufügen . Ich habe auch vergessen zu erwähnen, dass Reverse Looping eine signifikante Optimierung für 8-Bit-Prozessoren wie den 6502 darstellt, bei denen Sie den Vergleich wirklich kostenlos erhalten!
Joeytwiddle
Die gleiche Antwort ist viel prägnanter gegeben hier (auf einer anderen Frage).
Joeytwiddle
84
Einige Sprachen im C- Stil verwenden foreachzum Durchlaufen von Aufzählungen. In JavaScript erfolgt dies mit der for..inSchleifenstruktur :
var index,
value;for(index in obj){
value = obj[index];}
Es gibt einen Haken. for..indurchläuft jedes der aufzählbaren Elemente des Objekts und die Elemente auf seinem Prototyp. Um zu vermeiden, dass Werte gelesen werden, die vom Prototyp des Objekts geerbt werden, überprüfen Sie einfach, ob die Eigenschaft zum Objekt gehört:
for(i in obj){if(obj.hasOwnProperty(i)){//do stuff}}
Darüber hinaus hat ECMAScript 5 eine forEachMethode hinzugefügt , mit Array.prototypeder ein Array mithilfe eines Calbacks aufgelistet werden kann (die Polyfüllung befindet sich in den Dokumenten, sodass Sie sie weiterhin für ältere Browser verwenden können):
Es ist wichtig zu beachten, dass Array.prototype.forEachdies nicht unterbrochen wird, wenn der Rückruf zurückkehrt false. jQuery und Underscore.js bieten ihre eigenen Variationen an each, um Schleifen bereitzustellen, die kurzgeschlossen werden können.
Wie kann man also aus einer ECMAScript5-foreach-Schleife ausbrechen, wie wir es für eine normale for-Schleife oder eine foreach-Schleife wie in C-Sprachen tun würden?
Ciaran Gallagher
5
@CiaranG, in JavaScript werden häufig eachMethoden angezeigt, return falsemit denen die Schleife verlassen werden kann. forEachDies ist jedoch keine Option. Ein externes Flag könnte verwendet werden (dh if (flag) return;es würde nur verhindern, dass der Rest des Funktionskörpers ausgeführt wird, und forEachweiterhin über die gesamte Sammlung iterieren.
zzzzBov
43
Wenn Sie ein Array durchlaufen möchten, verwenden Sie die dreiteilige Standardschleife for.
for(var i =0; i < myArray.length; i++){var arrayItem = myArray[i];}
Sie können einige Leistungsoptimierungen erzielen, indem Sie sie zwischenspeichern myArray.lengthoder rückwärts durchlaufen.
für (var i = 0, Länge = myArray.length; i <Länge; i ++) sollte es tun
Edson Medina
5
@EdsonMedina Dadurch wird auch eine neue globale Variable namens erstellt length. ;)
joeytwiddle
4
@joeytwiddle Ja, aber das würde den Rahmen dieses Beitrags sprengen. Sie werden trotzdem eine globale Variable i erstellen.
Edson Medina
6
@EdsonMedina Ich entschuldige mich, ich hatte das völlig falsch. Wenn Sie ,nach einer Aufgabe verwenden, wird kein neues globales Element eingeführt. Ihr Vorschlag ist also in Ordnung ! Ich habe dies für ein anderes Problem verwirrt: Wenn Sie =nach einer Zuweisung verwenden, wird eine neue globale erstellt.
Joeytwiddle
Beachten Sie, dass die Variable i nicht lokal für die Schleife ist. JavaScript hat keinen Blockbereich. Es ist wahrscheinlich besser, var i, length, arrayItem;vor der Schleife zu deklarieren , um dieses Missverständnis zu vermeiden.
James
35
Ich weiß, dass dies ein alter Beitrag ist, und es gibt bereits so viele gute Antworten. Der Vollständigkeit halber dachte ich, ich würde mit AngularJS einen anderen einwerfen . Dies gilt natürlich nur, wenn Sie Angular verwenden. Trotzdem möchte ich es trotzdem sagen.
angular.forEachNimmt 2 Argumente und ein optionales drittes Argument. Das erste Argument ist das Objekt (Array), über das iteriert werden soll, das zweite Argument ist die Iteratorfunktion und das optionale dritte Argument ist der Objektkontext (im Grunde genommen innerhalb der Schleife als 'this' bezeichnet).
Es gibt verschiedene Möglichkeiten, die forEach-Winkelschleife zu verwenden. Das einfachste und wahrscheinlich am häufigsten verwendete ist
var temp =[1,2,3];
angular.forEach(temp,function(item){//item will be each element in the array//do something});
Eine andere Möglichkeit, um Elemente von einem Array in ein anderes zu kopieren, ist
var temp =[1,2,3];var temp2 =[];
angular.forEach(temp,function(item){this.push(item);//"this" refers to the array passed into the optional third parameter so, in this case, temp2.}, temp2);
Obwohl Sie das nicht tun müssen, können Sie einfach Folgendes tun und es entspricht dem vorherigen Beispiel:
Jetzt gibt es Vor- und Nachteile der Verwendung der angular.forEachFunktion im Gegensatz zu der eingebauten forSchleife mit Vanillegeschmack .
Vorteile
Einfache Lesbarkeit
Einfache Beschreibbarkeit
Wenn verfügbar, angular.forEachwird die ES5 forEach-Schleife verwendet. Jetzt werde ich im Abschnitt Nachteile zur Effizienz kommen, da die forEach-Schleifen viel langsamer sind als die for-Schleifen. Ich erwähne dies als Profi, weil es schön ist, konsistent und standardisiert zu sein.
Betrachten Sie die folgenden 2 verschachtelten Schleifen, die genau dasselbe tun. Angenommen, wir haben zwei Arrays von Objekten und jedes Objekt enthält ein Array von Ergebnissen, von denen jedes eine Value-Eigenschaft hat, die eine Zeichenfolge ist (oder was auch immer). Nehmen wir an, wir müssen jedes der Ergebnisse durchlaufen und wenn sie gleich sind, führen Sie eine Aktion aus:
angular.forEach(obj1.results,function(result1){
angular.forEach(obj2.results,function(result2){if(result1.Value=== result2.Value){//do something}});});//exact same with a for loopfor(var i =0; i < obj1.results.length; i++){for(var j =0; j < obj2.results.length; j++){if(obj1.results[i].Value=== obj2.results[j].Value){//do something}}}
Zugegeben, dies ist ein sehr einfaches hypothetisches Beispiel, aber ich habe Triple Embedded for Loops mit dem zweiten Ansatz geschrieben und es war sehr schwer zu lesen und zu schreiben.
Nachteile
Effizienz. angular.forEachund die Eingeborenen forEachsind beide so viel langsamer als die normale forSchleife ... ungefähr 90% langsamer . Bei großen Datenmengen sollten Sie sich am besten an die native Datenmenge haltenfor Schleife.
Keine Unterbrechung, Fortsetzung oder Rückgabe der Unterstützung. continuewird tatsächlich durch " Unfall " unterstützt, um fortzufahren, indem angular.forEachSie einfach eine return;Anweisung in die Funktion einfügen, angular.forEach(array, function(item) { if (someConditionIsTrue) return; });die dazu führt, dass die Funktion für diese Iteration fortgesetzt wird. Dies liegt auch an der Tatsache, dass der Native forEachweder break unterstützt noch fortfährt.
Ich bin mir sicher, dass es noch verschiedene andere Vor- und Nachteile gibt, und Sie können gerne alle hinzufügen, die Sie für richtig halten. Ich bin der Meinung, dass Sie, wenn Sie Effizienz benötigen, nur die native forSchleife für Ihre Schleifenanforderungen verwenden müssen. Aber wenn Ihre Datensätze kleiner sind und eine gewisse Effizienz in Ordnung ist, um im Austausch für Lesbarkeit und Schreibbarkeit aufzugeben, dann werfen Sie auf jeden Fall einen angular.forEachin diesen bösen Jungen.
function forEach(list,callback){var length = list.length;for(var n =0; n < length; n++){
callback.call(list[n]);}}var myArray =['hello','world'];
forEach(
myArray,function(){
alert(this);// do something});
Der Iterator führt dabei eine unnötige Längenberechnung durch. Im Idealfall sollte die Listenlänge nur einmal berechnet werden.
MIdhun Krishna
2
@MIdhunKrishna Ich habe meine Antwort und die jsFiddle aktualisiert, aber sei dir bewusst, dass es nicht so einfach ist, wie du denkst. Überprüfen Sie diese Frage
Wahrscheinlich ist die for(i = 0; i < array.length; i++)Schleife nicht die beste Wahl. Warum? Wenn Sie dies haben:
var array =newArray();
array[1]="Hello";
array[7]="World";
array[11]="!";
Die Methode ruft von array[0]bis auf array[2]. Erstens werden zuerst Variablen referenziert, die Sie nicht einmal haben, zweitens würden Sie die Variablen nicht im Array haben, und drittens wird der Code dadurch mutiger. Schau her, es ist was ich benutze:
for(var i in array){var el = array[i];//If you want 'i' to be INT just put parseInt(i)//Do something with el}
Und wenn Sie möchten, dass es eine Funktion ist, können Sie dies tun:
function foreach(array, call){for(var i in array){
call(array[i]);}}
Wenn Sie brechen wollen, etwas mehr Logik:
function foreach(array, call){for(var i in array){if(call(array[i])==false){break;}}}
Es gibt drei Implementierungen foreachin jQuery wie folgt.
var a =[3,2];
$(a).each(function(){console.log(this.valueOf())});//Method 1
$.each(a,function(){console.log(this.valueOf())});//Method 2
$.each($(a),function(){console.log(this.valueOf())});//Method 3
Wobei ofdie damit verbundenen Kuriositäten vermieden werden inund es wie die forSchleife einer anderen Sprache funktioniert und letbindeti innerhalb der Schleife im Gegensatz zu innerhalb der Funktion.
Die geschweiften Klammern ( {}) können weggelassen werden, wenn nur ein Befehl vorhanden ist (z. B. im obigen Beispiel).
Eine einfache Lösung wäre jetzt die Verwendung der Bibliothek underscore.js . Es bietet viele nützliche Tools, z. B. eachund delegiert den Job automatisch an den Native, forEachfalls verfügbar.
for eachIn nativem JavaScript gibt es keine Schleife . Sie können entweder Bibliotheken verwenden, um diese Funktionalität zu erhalten (ich empfehle Underscore.js ), oder eine einfache forIn-Schleife verwenden.
Dies ist ein Iterator für eine nicht spärliche Liste, bei der der Index bei 0 beginnt. Dies ist das typische Szenario beim Umgang mit document.getElementsByTagName oder document.querySelectorAll.
function each( fn, data ){if(typeof fn =='string')eval('fn = function(data, i){'+ fn +'}');for(var i=0, L=this.length; i < L; i++)
fn.call(this[i], data, i );returnthis;}Array.prototype.each = each;
Anwendungsbeispiele:
Beispiel 1
var arr =[];[1,2,3].each(function(a){ a.push(this*this}, arr);
arr =[1,4,9]
each.call(document.getElementsByTagName('p'),"if( i % 2 == 0) this.className = data;",'red');
Jedes zweite p-Tag erhält class="red">
Beispiel 4
each.call(document.querySelectorAll('p.blue'),function(newClass, i){if( i <20)this.className = newClass;},'green');
Und schließlich werden die ersten 20 blauen p-Tags in grün geändert
Vorsicht bei der Verwendung von Zeichenfolgen als Funktion: Die Funktion wird außerhalb des Kontexts erstellt und sollte nur verwendet werden, wenn Sie sich des variablen Bereichs sicher sind. Andernfalls ist es besser, Funktionen zu übergeben, bei denen das Scoping intuitiver ist.
Es gibt einige Möglichkeiten , ein Array in JavaScript zu durchlaufen:
für - es ist das häufigste . Vollständiger Codeblock für die Schleife
var languages =["Java","JavaScript","C#","Python"];var i, len, text;for(i =0, len = languages.length, text =""; i < len; i++){
text += languages[i]+"<br>";}
document.getElementById("example").innerHTML = text;
Funktionsschleifen - forEach, map, filter, auch reduce(sie Schleife durch die Funktion, aber sie verwendet werden , wenn Sie etwas mit Ihrem Array tun müssen, usw.
// For example, in this case we loop through the number and double them up using the map functionvar numbers =[65,44,12,4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num *2});
Kleine Korrektur: forEachist keine "funktionale" Schleife, da sie keine neue Arrayzurückgibt (eigentlich gibt sie nichts zurück), sondern nur iteriert.
Nicholaswmin
19
ECMAScript 5 (die Version auf JavaScript) für die Arbeit mit Arrays:
forEach - Durchläuft jedes Element im Array und macht mit jedem Element alles, was Sie brauchen.
['C','D','E'].forEach(function(element, index){
console.log(element +" is #"+(index+1)+" in the musical scale");});// Output// C is the #1 in musical scale// D is the #2 in musical scale// E is the #3 in musical scale
Falls Sie sich mehr für den Betrieb eines Arrays mit einer eingebauten Funktion interessieren.
map - Erstellt ein neues Array mit dem Ergebnis der Rückruffunktion. Diese Methode eignet sich gut, wenn Sie die Elemente Ihres Arrays formatieren müssen.
// Let's upper case the items in the array['bob','joe','jen'].map(function(elem){return elem.toUpperCase();});// Output: ['BOB', 'JOE', 'JEN']
reduzieren - Wie der Name schon sagt, wird das Array auf einen einzelnen Wert reduziert, indem die angegebene Funktion aufgerufen wird, die das aktuelle Element und das Ergebnis der vorherigen Ausführung übergibt.
Es gibt keine eingebaute Fähigkeit, einzubrechen forEach. Um die Ausführung zu unterbrechen, gehen Sie Array#somewie folgt vor:
[1,2,3].some(function(number){return number ===1;});
Dies funktioniert, weil sometrue zurückgegeben wird, sobald einer der in Array-Reihenfolge ausgeführten Rückrufe true zurückgibt und die Ausführung des Restes kurzschließt.
Ursprüngliche Antwort
siehe Array-Prototyp für einige
Ich möchte dies auch als Komposition einer Rückwärtsschleife und als Antwort oben für jemanden hinzufügen, der diese Syntax ebenfalls möchte.
var foo =[object,object,object];for(var i = foo.length, item; item = foo[--i];){
console.log(item);}
Vorteile:
Der Vorteil dafür: Sie haben die Referenz bereits in der ersten, so dass sie später nicht mit einer anderen Zeile deklariert werden muss. Dies ist praktisch, wenn Sie das Objektarray durchlaufen.
Nachteile:
Dies wird immer dann unterbrochen, wenn die Referenz falsch ist - Falsey (undefiniert usw.). Es kann jedoch als Vorteil genutzt werden. Es würde jedoch das Lesen etwas erschweren. Und je nach Browser kann es "nicht" optimiert werden, um schneller als das Original zu arbeiten.
Die Destrukturierung und Verwendung des Spread-Operators hat sich für Neulinge in ECMAScript 6 als sehr gut lesbar / ästhetisch erwiesen, obwohl einige JavaScript-Veteranen dies möglicherweise als chaotisch betrachten. Junioren oder andere Leute könnten es nützlich finden.
In den folgenden Beispielen werden die for...ofAnweisung und die .forEachMethode verwendet.
Beispiele 6, 7 und 8 können mit beliebigen Funktionsschleifen verwendet werden , wie .map, .filter, .reduce, .sort, .every, .some. Weitere Informationen zu diesen Methoden finden Sie im Array-Objekt .
Beispiel 1: Normale for...ofSchleife - hier keine Tricks.
let arrSimple =['a','b','c'];for(let letter of arrSimple){
console.log(letter);}
let arrFruits =['apple','orange','banana'];for(let[firstLetter,...restOfTheWord]of arrFruits){// Create a shallow copy using the spread operatorlet[lastLetter]=[...restOfTheWord].reverse();
console.log(firstLetter, lastLetter, restOfTheWord);}
// let arrSimple = ['a', 'b', 'c'];// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`// this example will use a multi-dimensional array of the following format type:// `arrWithIndex: [number, string][]`let arrWithIndex =[[0,'a'],[1,'b'],[2,'c'],];// Same thing can be achieved using `.map` method// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);// Same thing can be achieved using `Object.entries`// NOTE: `Object.entries` method doesn't work on Internet Explorer unless it's polyfilled// let arrWithIndex = Object.entries(arrSimple);for(let[key, value]of arrWithIndex){
console.log(key, value);}
let arrWithIndex =[[0,'a'],[1,'b'],[2,'c'],];// Not to be confused here, `forEachIndex` is the real index// `mappedIndex` was created by "another user", so you can't really trust it
arrWithIndex.forEach(([mappedIndex, item], forEachIndex)=>{
console.log(forEachIndex, mappedIndex, item);});
let arrWithObjects =[{
name:'Jon',
age:32},{
name:'Elise',
age:33}];// NOTE: Destructuring objects while using shorthand functions// are required to be surrounded by parentheses
arrWithObjects.forEach(({ name, age: aliasForAge })=>{
console.log(name, aliasForAge)});
Ein Weg, der Ihrer Idee am nächsten kommt, wäre die Verwendung Array.forEach()einer Schließfunktion, die für jedes Element des Arrays ausgeführt wird.
myArray.forEach((item)=>{// Do something
console.log(item);});
Ein anderer praktikabler Weg wäre die Verwendung, Array.map()die auf die gleiche Weise funktioniert, aber auch alle Werte, die Sie zurückgeben, in einem neuen Array zurückgibt (im Wesentlichen jedes Element einem neuen zuzuordnen), wie folgt:
Dies ist falsch, mapmutiert die Elemente des Arrays nicht, da ein neues Array zurückgegeben wird, wobei die Elemente dieses neuen Arrays das Ergebnis der Anwendung der Funktion auf die Elemente des alten Arrays sind.
Jesús Franco
Ich habe nie gesagt, dass kein neues Array zurückgegeben wird. Ich habe mich auf die von der Funktion vorgenommene Änderung bezogen. Aber hier werde ich es in der Antwort ändern.
Ante Jablan Adamović
wieder falsch, die Karte ändert oder mutiert nicht alle Elemente im ursprünglichen Array. Ich habe die Antwort vorgeschlagen und bearbeitet, wobei hervorgehoben wird, dass die Karte mit einer Kopie der ursprünglichen Elemente funktioniert , wobei das ursprüngliche Array überhaupt unberührt bleibt
Jesús Franco
7
Sie können forEach so anrufen:
forEachiteriert über das von Ihnen bereitgestellte Array und für jede Iteration, elementdie den Wert dieser Iteration enthält. Wenn Sie einen Index benötigen, können Sie den aktuellen Index erhalten, indem Sie den übergebeni als zweiten Parameter in der Rückruffunktion für forEach übergeben.
Foreach ist im Grunde eine Funktion hoher Ordnung, die eine andere Funktion als Parameter verwendet.
let theArray=[1,3,2];
theArray.forEach((element)=>{// Use the element of the array
console.log(element)}
Ausgabe:
132
Sie können auch über ein Array wie folgt iterieren:
for(let i=0; i<theArray.length; i++){
console.log(i);// i will have the value of each index}
Wenn Sie ein Array von Objekten mit der Pfeilfunktion durchlaufen möchten:
let arr =[{name:'john', age:50},{name:'clark', age:19},{name:'mohan', age:26}];
arr.forEach((person)=>{
console.log('I am '+ person.name +' and I am '+ person.age +' old');})
Die Lambda-Syntax funktioniert normalerweise nicht in Internet Explorer 10 oder niedriger.
Ich benutze normalerweise die
[].forEach.call(arrayName,function(value,index){
console.log("value of the looped element"+ value);
console.log("index of the looped element"+ index);});
Wenn Sie ein jQuery- Fan sind und bereits eine jQuery-Datei ausgeführt wird, sollten Sie die Positionen der Index- und Wertparameter umkehren
$("#ul>li").each(function(**index, value**){
console.log("value of the looped element"+ value);
console.log("index of the looped element"+ index);});
Wenn Sie ein massives Array haben, sollten Sie es verwenden iterators, um eine gewisse Effizienz zu erzielen. Iteratoren ist eine Eigenschaft bestimmter JavaScript Sammlungen (wie Map, Set, String, Array). Auch for..ofverwendet iteratorunter der Haube.
Iteratoren verbessern die Effizienz, indem Sie die Elemente in einer Liste einzeln als Stream verwenden können. Das Besondere an einem Iterator ist, wie er eine Sammlung durchläuft. Andere Schleifen müssen die gesamte Sammlung im Voraus laden, um sie zu durchlaufen, während ein Iterator nur die aktuelle Position in der Sammlung kennen muss.
Sie greifen auf das aktuelle Element zu, indem Sie die nextMethode des Iterators aufrufen . Die nächste Methode gibt valuedas aktuelle Element und a zurück, booleanum anzuzeigen, wann Sie das Ende der Sammlung erreicht haben. Das folgende Beispiel zeigt das Erstellen eines Iterators aus einem Array.
Verwandeln Sie Ihr reguläres Array mit der folgenden values()Methode in einen Iterator :
const myArr =[2,3,4]let it = myArr.values();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Heute (2019.12.18) Ich führe Test auf meinem macOS v10.13.6 (High Sierra), auf Chrome v 79.0, Safari v13.0.4 und Firefox v71.0 (64 bit) - Schlussfolgerungen über Optimierung (und Mikro-Optimierung der Normalerweise lohnt es sich nicht, es in den Code einzuführen, da der Nutzen gering ist, aber die Komplexität des Codes zunimmt.
Es sieht so aus, als ob das traditionelle for i( Aa ) eine gute Wahl ist, um schnellen Code in allen Browsern zu schreiben.
Die anderen Lösungen wie for-of( Ad ), alle in Gruppe C. ... sind normalerweise 2 bis 10 (und mehr) Mal langsamer als Aa , aber für kleine Arrays ist es in Ordnung, sie zu verwenden - um die Klarheit des Codes zu erhöhen.
Die in n( Ab, Bb, Be ) zwischengespeicherten Schleifen mit Array-Länge sind manchmal schneller, manchmal nicht. Wahrscheinlich erkennen Compiler diese Situation automatisch und führen das Caching ein. Die Geschwindigkeitsunterschiede zwischen der zwischengespeicherten und der nicht zwischengespeicherten Version ( Aa, Ba, Bd ) betragen etwa ~ 1%. Es sieht also so aus, als wäre einführen neine Mikrooptimierung .
Die i--wie Lösungen , wo die Schleife beginnt mit dem letzten Array - Elemente ( Ac, Bc ) sind in der Regel ca. 30% langsamer als Vorwärts-Lösungen - wahrscheinlich der Grund dafür ist die Art und Weise der CPU - Speicher - Cache Arbeits - Vorwärts-Speicher Lesen ist optimal für die CPU - Caching). Es wird empfohlen, solche Lösungen NICHT zu verwenden.
Einzelheiten
In Tests berechnen wir die Summe der Array-Elemente. Ich führe einen Test für kleine Arrays (10 Elemente) und große Arrays (1M Elemente) durch und teile sie in drei Gruppen ein:
Wenn wir über ein Array iterieren, möchten wir häufig eines der folgenden Ziele erreichen:
Wir möchten das Array durchlaufen und ein neues Array erstellen:
Array.prototype.map
Wir möchten das Array durchlaufen und kein neues Array erstellen:
Array.prototype.forEach
for..ofSchleife
In JavaScript gibt es viele Möglichkeiten, diese beiden Ziele zu erreichen. Einige sind jedoch bequemer als andere. Im Folgenden finden Sie einige häufig verwendete Methoden (die bequemste IMO), um die Array-Iteration in JavaScript durchzuführen.
Neues Array erstellen: Map
map()ist eine Funktion, mit Array.prototypeder jedes Element eines Arrays transformiert und dann ein neues Array zurückgegeben werden kann. map()Nimmt als Argument eine Rückruffunktion und funktioniert folgendermaßen:
let arr =[1,2,3,4,5];let newArr = arr.map((element, index, array)=>{return element *2;})
console.log(arr);
console.log(newArr);
Der Rückruf, den wir map()als Argument übergeben haben, wird für jedes Element ausgeführt. Dann wird ein Array zurückgegeben, das dieselbe Länge wie das ursprüngliche Array hat. In diesem neuen Array wird das Element durch die Rückruffunktion transformiert, die als Argument an übergeben wirdmap() .
Der deutliche Unterschied zwischen mapeinem anderen Schleifenmechanismus wie forEachund einer for..ofSchleife besteht darin, dass mapein neues Array zurückgegeben wird und das alte Array intakt bleibt (es sei denn, Sie manipulieren es explizit mit "think like" splice).
Beachten Sie außerdem, dass der mapRückruf der Funktion die Indexnummer der aktuellen Iteration als zweites Argument bereitstellt. Gibt das dritte Argument außerdem das Array an, auf dem mapaufgerufen wurde? Manchmal können diese Eigenschaften sehr nützlich sein.
Schleife mit forEach
forEachist eine Funktion, die sich befindet und Array.prototypeeine Rückruffunktion als Argument verwendet. Diese Rückruffunktion wird dann für jedes Element im Array ausgeführt. Im Gegensatz zur map()Funktion gibt die Funktion forEach nichts zurück ( undefined). Zum Beispiel:
let arr =[1,2,3,4,5];
arr.forEach((element, index, array)=>{
console.log(element *2);if(index ===4){
console.log(array)}// index, and oldArray are provided as 2nd and 3th argument by the callback})
console.log(arr);
Genau wie die mapFunktion forEachliefert der Rückruf die Indexnummer der aktuellen Iteration als zweites Argument. Gibt das dritte Argument auch das Array an, für das forEachaufgerufen wurde?
Durchlaufen Sie Elemente mit for..of
Die for..ofSchleife durchläuft jedes Element eines Arrays (oder eines anderen iterierbaren Objekts). Es funktioniert folgendermaßen:
let arr =[1,2,3,4,5];for(let element of arr){
console.log(element *2);}
Im obigen Beispiel elementsteht für ein Array-Element und arrist das Array, das wir schleifen möchten. Beachten Sie, dass der Nameelement willkürlich ist und wir einen anderen Namen wie 'el' oder etwas aussagekräftigeres wählen könnten, wenn dies zutreffend ist.
Verwechseln Sie die for..inSchleife nicht mit der for..ofSchleife. for..inDurchläuft alle aufzählbaren Eigenschaften des Arrays, während die for..ofSchleife nur die Array-Elemente durchläuft. Zum Beispiel:
let arr =[1,2,3,4,5];
arr.foo ='foo';for(let element of arr){
console.log(element);}for(let element in arr){
console.log(element);}
forEach
und nicht nurfor
. wie gesagt, in c # war es ein bisschen anders, und das hat mich verwirrt :)i < len
undi++
kann durch den Motor durchgeführt werden, anstatt durch den Interpreter.)Antworten:
TL; DR
for-in
Sie es nur, wenn Sie es mit Schutzmaßnahmen verwenden oder zumindest wissen, warum es Sie beißen könnte.Ihre besten Wetten sind normalerweise
for-of
Schleife (nur ES2015 +),Array#forEach
(spec
|MDN
) (oder seine Verwandtensome
und dergleichen) (nur ES5 +),for
Schleife,for-in
mit Schutzmaßnahmen.Aber es gibt noch viel mehr zu entdecken, weiterzulesen ...
JavaScript verfügt über eine leistungsstarke Semantik zum Durchlaufen von Arrays und Array-ähnlichen Objekten. Ich habe die Antwort in zwei Teile geteilt: Optionen für echte Arrays und Optionen für Dinge, die nur Array- ähnlich sind , wie das
arguments
Objekt, andere iterierbare Objekte (ES2015 +), DOM-Sammlungen und so weiter.Ich werde schnell beachten Sie, dass Sie die ES2015 - Optionen können nun auch auf ES5 - Motoren, von transpiling ES2015 bis ES5. Suchen Sie nach "ES2015 transpiling" / "ES6 transpiling" für mehr ...
Okay, schauen wir uns unsere Optionen an:
Für tatsächliche Arrays
Sie haben drei Optionen in ECMAScript 5 ("ES5"), der derzeit am weitesten verbreiteten Version, und zwei weitere in ECMAScript 2015 ("ES2015", "ES6"):
forEach
und verwandte (ES5 +)for
Schleifefor-in
richtigfor-of
(implizit einen Iterator verwenden) (ES2015 +)Einzelheiten:
1. Verwenden
forEach
und verwandtIn jeder vage modernen Umgebung (also nicht in IE8), in der Sie Zugriff auf die
Array
von ES5 hinzugefügten Funktionen haben (direkt oder mithilfe von Polyfills), können SieforEach
(spec
|MDN
) verwenden:forEach
Akzeptiert eine Rückruffunktion und optional einen Wert, derthis
beim Aufrufen dieses Rückrufs verwendet werden soll (oben nicht verwendet). Der Rückruf wird für jeden Eintrag im Array aufgerufen, um nicht vorhandene Einträge in dünn besetzten Arrays zu überspringen. Obwohl ich oben nur ein Argument verwendet habe, wird der Rückruf mit drei aufgerufen: Der Wert jedes Eintrags, der Index dieses Eintrags und ein Verweis auf das Array, über das Sie iterieren (falls Ihre Funktion es noch nicht zur Hand hat ).Sofern Sie nicht veraltete Browser wie IE8 unterstützen (NetApps weist zum Zeitpunkt dieses Schreibens im September 2016 einen Marktanteil von etwas mehr als 4% auf), können Sie diese
forEach
problemlos auf einer Allzweck-Webseite ohne Shim verwenden. Wenn Sie veraltete Browser unterstützen müssen, ist das Shimmen / PolyfillingforEach
einfach (suchen Sie nach "es5 shim" für mehrere Optionen).forEach
hat den Vorteil, dass Sie keine Indexierungs- und Wertvariablen im enthaltenen Bereich deklarieren müssen, da sie als Argumente für die Iterationsfunktion bereitgestellt werden und sich so gut auf diese Iteration beschränken.Wenn Sie sich Sorgen über die Laufzeitkosten für einen Funktionsaufruf für jeden Array-Eintrag machen, sollten Sie dies nicht tun. Details .
Darüber hinaus gibt
forEach
es die Funktion "Schleife durch alle", aber ES5 hat mehrere andere nützliche Funktionen definiert, mit denen Sie sich durch das Array arbeiten und Dinge erledigen können, darunter:every
(stoppt die Schleife, wenn der Rückruf zum ersten Mal zurückkehrtfalse
oder etwas Falsches)some
(stoppt die Schleife, wenn der Rückruf zum ersten Mal zurückkehrttrue
oder etwas Wahres)filter
(Erstellt ein neues Array mit Elementen, bei denen die Filterfunktion zurückgegeben wird,true
und lässt diejenigen weg, bei denen sie zurückgegeben wird.false
)map
(Erstellt ein neues Array aus den vom Rückruf zurückgegebenen Werten.)reduce
(Baut einen Wert auf, indem der Rückruf wiederholt aufgerufen wird und vorherige Werte übergeben werden. Einzelheiten finden Sie in der Spezifikation. Nützlich zum Summieren des Inhalts eines Arrays und vieler anderer Dinge.)reduceRight
(wiereduce
, funktioniert aber eher in absteigender als in aufsteigender Reihenfolge)2. Verwenden Sie eine einfache
for
SchleifeManchmal sind die alten Wege die besten:
Wenn die Länge des Feldes wird nicht während der Schleife ändern, und es ist in leistungskritischen Code (unwahrscheinlich), eine etwas kompliziertere Version die Länge vorne greifen könnte ein seine winzig bisschen schneller:
Und / oder rückwärts zählen:
Bei modernen JavaScript-Engines ist es jedoch selten, dass Sie das letzte Stück Saft herausholen müssen.
In ES2015 und höher können Sie Ihre Index- und Wertvariablen lokal für die
for
Schleife festlegen :Code-Snippet anzeigen
Und wenn Sie dies tun, wird nicht nur,
value
sondern auchindex
für jede Schleifeniteration neu erstellt, was bedeutet, dass im Schleifenkörper erstellte Abschlüsse einen Verweis auf dasindex
(undvalue
) enthalten, das für diese bestimmte Iteration erstellt wurde:Code-Snippet anzeigen
Wenn Sie fünf Divs hatten, erhalten Sie "Index ist: 0", wenn Sie auf den ersten geklickt haben, und "Index ist: 4", wenn Sie auf den letzten geklickt haben. Dies funktioniert nicht , wenn Sie
var
anstelle von verwendenlet
.3.
for-in
Richtig verwendenSie erhalten die Menschen sagen , die Sie zu verwenden
for-in
, aber das ist nicht das, wasfor-in
für ist .for-in
Durchläuft die aufzählbaren Eigenschaften eines Objekts und nicht die Indizes eines Arrays. Die Bestellung ist nicht garantiert , auch nicht in ES2015 (ES6). ES2015 + definiert zwar eine Reihenfolge für Objekteigenschaften (via[[OwnPropertyKeys]]
,[[Enumerate]]
und Dinge, die sie verwendenObject.getOwnPropertyKeys
), aber es wurde nicht definiert,for-in
welche Reihenfolge dieser Reihenfolge folgen würde. ES2020 hat es jedoch getan. (Details in dieser anderen Antwort .)Die einzigen realen Anwendungsfälle für
for-in
ein Array sind:Betrachten Sie nur das erste Beispiel: Sie können
for-in
diese spärlichen Array-Elemente verwenden, wenn Sie geeignete Sicherheitsvorkehrungen treffen:Beachten Sie die drei Prüfungen:
Dass das Objekt eine eigene Eigenschaft mit diesem Namen hat (keine, die es von seinem Prototyp erbt), und
Dass der Schlüssel alle Dezimalstellen sind (z. B. normale Zeichenfolgenform, keine wissenschaftliche Notation), und
Dass der Wert des Schlüssels, wenn er zu einer Zahl gezwungen wird, <= 2 ^ 32 - 2 ist (was 4,294,967,294 ist). Woher kommt diese Nummer? Es ist Teil der Definition eines Array-Index in der Spezifikation . Andere Zahlen (Nicht-Ganzzahlen, negative Zahlen, Zahlen größer als 2 ^ 32 - 2) sind keine Array-Indizes. Der Grund, warum es 2 ^ 32 - 2 ist, ist, dass dadurch der größte Indexwert niedriger als 2 ^ 32 - 1 wird , was der maximale Wert ist, den ein Array haben
length
kann. (ZB passt die Länge eines Arrays in eine 32-Bit-Ganzzahl ohne Vorzeichen.) (Wir bitten RobG, in einem Kommentar in meinem Blog-Beitrag darauf hinzuweisen, dass mein vorheriger Test nicht ganz richtig war.)Das würden Sie natürlich nicht im Inline-Code tun. Sie würden eine Dienstprogrammfunktion schreiben. Vielleicht:
Code-Snippet anzeigen
4. Verwenden Sie
for-of
(verwenden Sie implizit einen Iterator) (ES2015 +)ES2015 fügte Iteratoren zu JavaScript hinzu. Der einfachste Weg, Iteratoren zu verwenden, ist die neue
for-of
Anweisung. Es sieht aus wie das:Unter der Decke erhält das einen Iterator aus dem Array und durchläuft es, wobei die Werte daraus abgerufen werden. Dies hat nicht das Problem, das bei der Verwendung
for-in
auftritt, da ein vom Objekt (dem Array) definierter Iterator verwendet wird und Arrays definieren, dass ihre Iteratoren ihre Einträge (nicht ihre Eigenschaften) durchlaufen . Anders alsfor-in
in ES5 ist die Reihenfolge, in der die Einträge besucht werden, die numerische Reihenfolge ihrer Indizes.5. Verwenden Sie explizit einen Iterator (ES2015 +)
Manchmal möchten Sie möglicherweise einen Iterator explizit verwenden . Sie können das auch tun, obwohl es viel klobiger ist als
for-of
. Es sieht aus wie das:Der Iterator ist ein Objekt, das mit der Iteratordefinition in der Spezifikation übereinstimmt. Die
next
Methode gibt bei jedem Aufruf ein neues Ergebnisobjekt zurück . Das Ergebnisobjekt hat eine Eigenschaft,done
die uns mitteilt, ob es fertig ist, und eine Eigenschaftvalue
mit dem Wert für diese Iteration. (done
ist optional, wenn es wärefalse
,value
ist optional, wenn es wäreundefined
.)Die Bedeutung von
value
variiert je nach Iterator. Arrays unterstützen (mindestens) drei Funktionen, die Iteratoren zurückgeben:values()
: Dies ist die, die ich oben verwendet habe. Es gibt einen Iterator , wobei jedesvalue
der Array - Eintrag für diese Iteration ("a"
,"b"
, und"c"
in dem Beispiel weiter oben).keys()
: Gibt einen Iterator zurück, wobei jedervalue
der Schlüssel für diese Iteration ist (für unserea
obigen wäre das also"0"
dann"1"
, dann"2"
).entries()
: Gibt einen Iterator zurück, wobei jedesvalue
ein Array im Formular[key, value]
für diese Iteration ist.Für Array-ähnliche Objekte
Abgesehen von echten Arrays gibt es auch Array-ähnliche Objekte, die eine
length
Eigenschaft und Eigenschaften mit numerischen Namen haben:NodeList
Instanzen, dasarguments
Objekt usw. Wie durchlaufen wir ihren Inhalt?Verwenden Sie eine der oben genannten Optionen für Arrays
Zumindest einige und möglicherweise die meisten oder sogar alle der oben genannten Array-Ansätze gelten häufig gleich gut für Array-ähnliche Objekte:
Verwendung
forEach
und verwandte (ES5 +)Die verschiedenen Funktionen
Array.prototype
sind "absichtlich generisch" und können normalerweise für Array-ähnliche Objekte überFunction#call
oder verwendet werdenFunction#apply
. (Siehe die Einschränkung für vom Host bereitgestellte Objekte am Ende dieser Antwort, aber es ist ein seltenes Problem.)Angenommen , Sie verwenden wollten
forEach
auf einemNode
‚s -childNodes
Eigenschaft. Du würdest das tun:Wenn Sie dies häufig tun, möchten Sie möglicherweise eine Kopie der Funktionsreferenz zur Wiederverwendung in eine Variable aufnehmen, z.
Verwenden Sie eine einfache
for
SchleifeOffensichtlich gilt eine einfache
for
Schleife für Array-ähnliche Objekte.verwenden Sie
for-in
richtigfor-in
mit den gleichen Sicherheitsvorkehrungen wie mit einem Array sollte auch mit Array-ähnlichen Objekten funktionieren; Möglicherweise gilt die Einschränkung für vom Host bereitgestellte Objekte unter Nummer 1 oben.Verwenden
for-of
(implizit einen Iterator verwenden) (ES2015 +)for-of
verwendet den vom Objekt bereitgestellten Iterator (falls vorhanden). Dies schließt vom Host bereitgestellte Objekte ein. Beispielsweise wurde die Spezifikation für dasNodeList
vonquerySelectorAll
aktualisiert, um die Iteration zu unterstützen. Die Spezifikation für dasHTMLCollection
vongetElementsByTagName
war nicht.Verwenden Sie explizit einen Iterator (ES2015 +)
Siehe # 4.
Erstellen Sie ein echtes Array
In anderen Fällen möchten Sie möglicherweise ein Array-ähnliches Objekt in ein echtes Array konvertieren. Das ist überraschend einfach:
Verwenden Sie die
slice
Methode der ArraysWir können die
slice
Methode von Arrays verwenden, die wie die anderen oben genannten Methoden "absichtlich generisch" ist und daher mit Array-ähnlichen Objekten wie diesen verwendet werden kann:Wenn wir beispielsweise a
NodeList
in ein echtes Array konvertieren möchten , können wir Folgendes tun:Weitere Informationen zu vom Host bereitgestellten Objekten finden Sie weiter unten. Beachten Sie insbesondere, dass dies in IE8 und früheren Versionen fehlschlägt, sodass Sie vom Host bereitgestellte Objekte nicht so verwenden können
this
.Verwenden Sie die Spread-Syntax (
...
)Es ist auch möglich, die Spread-Syntax von ES2015 mit JavaScript-Engines zu verwenden, die diese Funktion unterstützen. Wie
for-of
dies den verwendet Iterator vom Objekt zur Verfügung gestellt (siehe # 4 im vorherigen Abschnitt):Wenn wir zum Beispiel a
NodeList
in ein echtes Array konvertieren möchten , wird dies mit der Spread-Syntax ziemlich prägnant:Verwenden
Array.from
Array.from
(spec) | (MDN) (ES2015 +, aber leicht polyfüllbar) erstellt ein Array aus einem Array-ähnlichen Objekt, wobei die Einträge optional zuerst über eine Zuordnungsfunktion übergeben werden. Damit:Wenn Sie ein Array der Tag-Namen der Elemente mit einer bestimmten Klasse abrufen möchten, verwenden Sie die Zuordnungsfunktion:
Vorsichtsmaßnahme für vom Host bereitgestellte Objekte
Wenn Sie
Array.prototype
Funktionen mit vom Host bereitgestellten Array-ähnlichen Objekten verwenden (DOM-Listen und andere vom Browser anstelle der JavaScript-Engine bereitgestellte Dinge), müssen Sie sicherstellen, dass Sie in Ihren Zielumgebungen testen, um sicherzustellen, dass sich das vom Host bereitgestellte Objekt ordnungsgemäß verhält . Die meisten verhalten sich (jetzt) richtig , aber es ist wichtig zu testen. Der Grund dafür ist, dass die meistenArray.prototype
Methoden, die Sie wahrscheinlich verwenden möchten, auf dem vom Host bereitgestellten Objekt basieren, das eine ehrliche Antwort auf die abstrakte[[HasProperty]]
Operation gibt. Zum jetzigen Zeitpunkt leisten Browser sehr gute Arbeit, aber die 5.1-Spezifikation hat die Möglichkeit berücksichtigt, dass ein vom Host bereitgestelltes Objekt möglicherweise nicht ehrlich ist. Es ist in §8.6.2 , mehrere Absätze unter der großen Tabelle am Anfang dieses Abschnitts), wo es heißt:(Ich konnte nicht den äquivalent Wortschwall in der ES2015 - Spezifikation finden, aber es ist gesprungen , der Fall noch sein.) Auch hier, wie dies den gemeinsamen Host-bereitgestellt Schreiben Array-ähnliche Objekte in modernen Browsern [
NodeList
Instanzen, zum Beispiel] tun Griffes[[HasProperty]]
richtig, aber es ist wichtig zu testen.)quelle
.forEach
nicht effizient gebrochen werden kann. Sie müssen eine Ausnahme auslösen, um die Pause auszuführen.some
. (Ich hätte es vorgezogen, auch das Brechen zuzulassenforEach
, aber sie haben mich nicht gefragt. ;-)),
Afterk=0
, kein;
. Denken Sie daran, Programmierung ist viele Dinge, von denen eines viel Liebe zum Detail ist ... :-)length
ist keine Methode). :-)Hinweis : Diese Antwort ist hoffnungslos veraltet. Schauen Sie sich für einen moderneren Ansatz die auf einem Array verfügbaren Methoden an . Methoden von Interesse könnten sein:
Die Standardmethode zum Iterieren eines Arrays in JavaScript ist eine Vanille-
for
Schleife:Beachten Sie jedoch, dass dieser Ansatz nur dann gut ist, wenn Sie ein dichtes Array haben und jeder Index von einem Element belegt ist. Wenn das Array spärlich ist, können bei diesem Ansatz Leistungsprobleme auftreten, da Sie viele Indizes durchlaufen, die im Array nicht wirklich vorhanden sind. In diesem Fall
for .. in
könnte eine Schleife eine bessere Idee sein. Allerdings müssen Sie die entsprechenden Schutzmaßnahmen verwenden , die nur die gewünschten Eigenschaften des Arrays zu gewährleisten (das heißt, die Array - Elemente) beaufschlagt werden, da diefor..in
-loop auch in älterem Browser aufgelistet werden, oder wenn die zusätzlichen Eigenschaften sind definiert alsenumerable
.In ECMAScript 5 gibt es eine forEach-Methode für den Array-Prototyp, die jedoch in älteren Browsern nicht unterstützt wird. Um es konsistent verwenden zu können, müssen Sie entweder über eine Umgebung verfügen, die es unterstützt (z. B. Node.js für serverseitiges JavaScript), oder eine "Polyfill" verwenden. Die Polyfüllung für diese Funktionalität ist jedoch trivial und da sie das Lesen des Codes erleichtert, ist sie eine gute Polyfüllung.
quelle
for(instance in objArray)
eine korrekte Verwendung nicht? es sieht für mich einfacher aus, aber ich höre, dass Sie davon sprechen, dass es nicht die richtige Art der Verwendung ist?var
Schlüsselwort zu deklarieren . Wenn wir ein Semikolon verwendet hätten,element
wäre es im globalen Bereich deklariert worden (oder besser gesagt, JSHint hätte uns angeschrien, bevor es die Produktion erreichte).Wenn Sie die jQuery- Bibliothek verwenden, können Sie jQuery.each verwenden :
BEARBEITEN:
Gemäß der Frage möchte der Benutzer Code in Javascript anstelle von jquery, so dass die Bearbeitung erfolgt
quelle
Schleife rückwärts
Ich denke, die Umkehrung der Schleife verdient hier eine Erwähnung:
Vorteile:
len
Variable deklarieren oderarray.length
bei jeder Iteration vergleichen, was eine winzige Optimierung sein könnte.array[i]
), überspringt eine Vorwärtsschleife das Element, das nach links in Position i verschoben wurde , oder verarbeitet das i- te Element erneut nach rechts verschoben. In einem traditionellen for - Schleife, Sie könnten aktualisieren i zum nächsten Punkt zu Punkt , dass Bedürfnisse der Verarbeitung - 1, sondern einfach die Umkehrung der Richtung der Iteration ist oft eine einfachere und elegantere Lösung .forEach()
und gegen ES6 verliertfor ... of
.Nachteile:
Soll ich es immer benutzen?
Einige Entwickler verwenden standardmäßig die umgekehrte for-Schleife , es sei denn, es gibt einen guten Grund, eine Vorwärtsschleife durchzuführen.
Obwohl die Leistungssteigerungen normalerweise unbedeutend sind, schreit es:
In der Praxis ist dies jedoch kein verlässlicher Hinweis auf die Absicht, da es nicht von den Gelegenheiten zu unterscheiden ist, in denen Sie sich um die Reihenfolge kümmern und wirklich eine umgekehrte Schleife durchführen müssen. Tatsächlich wäre also ein anderes Konstrukt erforderlich, um die Absicht "egal" genau auszudrücken, was derzeit in den meisten Sprachen, einschließlich ECMAScript, nicht verfügbar ist, aber beispielsweise aufgerufen werden könnte
forEachUnordered()
.Wenn die Reihenfolge keine Rolle spielt und die Effizienz ein Problem darstellt (in der innersten Schleife eines Spiels oder einer Animations-Engine), kann es akzeptabel sein, die umgekehrte for-Schleife als Ausgangsmuster zu verwenden. Denken Sie daran, dass eine umgekehrte for-Schleife im vorhandenen Code nicht unbedingt bedeutet, dass die Reihenfolge irrelevant ist!
Es war besser, forEach () zu verwenden
Im Allgemeinen habe ich für Code auf höherer Ebene, bei dem Klarheit und Sicherheit eine größere
Array::forEach
Rolle spielen , zuvor empfohlen, als Standardmuster für Schleifen zu verwenden (obwohl ich heutzutage die Verwendung bevorzugefor..of
). Gründe,forEach
eine Rückwärtsschleife vorzuziehen , sind:for
undwhile
Schleifen versteckt ).Wenn Sie dann die umgekehrte for-Schleife in Ihrem Code sehen, ist dies ein Hinweis darauf, dass sie aus einem guten Grund umgekehrt ist (möglicherweise einer der oben beschriebenen Gründe). Wenn Sie eine herkömmliche Forward-for-Schleife sehen, kann dies darauf hinweisen, dass eine Verschiebung stattfinden kann.
(Wenn die Diskussion der Absicht für Sie keinen Sinn ergibt, können Sie und Ihr Code davon profitieren, Crockfords Vortrag über Programmierstil und Ihr Gehirn zu sehen .)
Es ist jetzt noch besser für ... zu verwenden!
Es gibt eine Debatte darüber, ob
for..of
oderforEach()
vorzuziehen sind:Für eine maximale Browserunterstützung ist
for..of
eine Polyfüllung für Iteratoren erforderlich , wodurch die Ausführung Ihrer App etwas langsamer und das Herunterladen etwas größer wird.Aus diesem Grunde (und Nutzung zu fördern
map
undfilter
,) einig Front-End - Styleguides verbietenfor..of
komplett!Die oben genannten Bedenken gelten jedoch nicht für Node.js-Anwendungen, die
for..of
jetzt gut unterstützt werden.Und
await
funktioniert außerdem nicht im InnerenforEach()
. Die Verwendungfor..of
ist in diesem Fall das klarste Muster .Persönlich neige ich dazu, das zu verwenden, was am einfachsten zu lesen ist, es sei denn, Leistung oder Minimierung sind zu einem Hauptanliegen geworden. Daher bevorzuge ich heutzutage die Verwendung
for..of
anstelle vonforEach()
, aber ich werde immermap
oderfilter
oderfind
odersome
wenn zutreffend verwenden. (Für meine Kollegen benutze ich seltenreduce
.)Wie funktioniert es?
Sie werden feststellen, dass dies
i--
der mittlere Satz ist (wo wir normalerweise einen Vergleich sehen) und der letzte Satz leer ist (wo wir normalerweise seheni++
). Das heißt, dasi--
wird auch als Voraussetzung für die Fortsetzung verwendet. Entscheidend ist, dass es vor jeder Iteration ausgeführt und überprüft wird.Wie kann es beginnen,
array.length
ohne zu explodieren?Da
i--
läuft vor jeder Iteration bei der ersten Iteration werden wir tatsächlich das Element zugreifen beiarray.length - 1
denen Probleme mit vermeidetArray-out-of-boundsundefined
Artikeln.Warum hört es nicht auf, vor Index 0 zu iterieren?
Die Schleife
i--
hört auf zu iterieren, wenn die Bedingung einen Falsey-Wert ergibt (wenn sie 0 ergibt).Der Trick ist, dass im Gegensatz dazu
--i
der nachfolgendei--
Operator dekrementiert,i
aber den Wert vor dem Dekrement liefert . Ihre Konsole kann dies demonstrieren:> var i = 5; [i, i--, i];
[5, 5, 4]
Bei der letzten Iteration war ich zuvor 1 und der
i--
Ausdruck ändert ihn in 0 , ergibt aber tatsächlich 1 (wahr), und so besteht die Bedingung. Bei der nächsten Iterationi--
ändert sich i auf -1 , ergibt jedoch 0 (Falsey), wodurch die Ausführung sofort aus dem unteren Bereich der Schleife herausfällt.In der traditionellen Forwards for-Schleife
i++
und++i
sind austauschbar (wie Douglas Crockford betont). Umgekehrt müssen wir jedoch bei der umgekehrten for-Schleife bleiben, da unser Dekrement auch unser Bedingungsausdruck ist,i--
wenn wir das Element bei Index 0 verarbeiten möchten.Wissenswertes
Einige Leute zeichnen gerne einen kleinen Pfeil in die umgekehrte
for
Schleife und beenden mit einem Augenzwinkern:Dank geht an WYL, weil er mir die Vorteile und Schrecken der umgekehrten for-Schleife gezeigt hat.
quelle
Einige Sprachen im C- Stil verwenden
foreach
zum Durchlaufen von Aufzählungen. In JavaScript erfolgt dies mit derfor..in
Schleifenstruktur :Es gibt einen Haken.
for..in
durchläuft jedes der aufzählbaren Elemente des Objekts und die Elemente auf seinem Prototyp. Um zu vermeiden, dass Werte gelesen werden, die vom Prototyp des Objekts geerbt werden, überprüfen Sie einfach, ob die Eigenschaft zum Objekt gehört:Darüber hinaus hat ECMAScript 5 eine
forEach
Methode hinzugefügt , mitArray.prototype
der ein Array mithilfe eines Calbacks aufgelistet werden kann (die Polyfüllung befindet sich in den Dokumenten, sodass Sie sie weiterhin für ältere Browser verwenden können):Es ist wichtig zu beachten, dass
Array.prototype.forEach
dies nicht unterbrochen wird, wenn der Rückruf zurückkehrtfalse
. jQuery und Underscore.js bieten ihre eigenen Variationen aneach
, um Schleifen bereitzustellen, die kurzgeschlossen werden können.quelle
each
Methoden angezeigt,return false
mit denen die Schleife verlassen werden kann.forEach
Dies ist jedoch keine Option. Ein externes Flag könnte verwendet werden (dhif (flag) return;
es würde nur verhindern, dass der Rest des Funktionskörpers ausgeführt wird, undforEach
weiterhin über die gesamte Sammlung iterieren.Wenn Sie ein Array durchlaufen möchten, verwenden Sie die dreiteilige Standardschleife
for
.Sie können einige Leistungsoptimierungen erzielen, indem Sie sie zwischenspeichern
myArray.length
oder rückwärts durchlaufen.quelle
length
. ;),
nach einer Aufgabe verwenden, wird kein neues globales Element eingeführt. Ihr Vorschlag ist also in Ordnung ! Ich habe dies für ein anderes Problem verwirrt: Wenn Sie=
nach einer Zuweisung verwenden, wird eine neue globale erstellt.var i, length, arrayItem;
vor der Schleife zu deklarieren , um dieses Missverständnis zu vermeiden.Ich weiß, dass dies ein alter Beitrag ist, und es gibt bereits so viele gute Antworten. Der Vollständigkeit halber dachte ich, ich würde mit AngularJS einen anderen einwerfen . Dies gilt natürlich nur, wenn Sie Angular verwenden. Trotzdem möchte ich es trotzdem sagen.
angular.forEach
Nimmt 2 Argumente und ein optionales drittes Argument. Das erste Argument ist das Objekt (Array), über das iteriert werden soll, das zweite Argument ist die Iteratorfunktion und das optionale dritte Argument ist der Objektkontext (im Grunde genommen innerhalb der Schleife als 'this' bezeichnet).Es gibt verschiedene Möglichkeiten, die forEach-Winkelschleife zu verwenden. Das einfachste und wahrscheinlich am häufigsten verwendete ist
Eine andere Möglichkeit, um Elemente von einem Array in ein anderes zu kopieren, ist
Obwohl Sie das nicht tun müssen, können Sie einfach Folgendes tun und es entspricht dem vorherigen Beispiel:
Jetzt gibt es Vor- und Nachteile der Verwendung der
angular.forEach
Funktion im Gegensatz zu der eingebautenfor
Schleife mit Vanillegeschmack .Vorteile
angular.forEach
wird die ES5 forEach-Schleife verwendet. Jetzt werde ich im Abschnitt Nachteile zur Effizienz kommen, da die forEach-Schleifen viel langsamer sind als die for-Schleifen. Ich erwähne dies als Profi, weil es schön ist, konsistent und standardisiert zu sein.Betrachten Sie die folgenden 2 verschachtelten Schleifen, die genau dasselbe tun. Angenommen, wir haben zwei Arrays von Objekten und jedes Objekt enthält ein Array von Ergebnissen, von denen jedes eine Value-Eigenschaft hat, die eine Zeichenfolge ist (oder was auch immer). Nehmen wir an, wir müssen jedes der Ergebnisse durchlaufen und wenn sie gleich sind, führen Sie eine Aktion aus:
Zugegeben, dies ist ein sehr einfaches hypothetisches Beispiel, aber ich habe Triple Embedded for Loops mit dem zweiten Ansatz geschrieben und es war sehr schwer zu lesen und zu schreiben.
Nachteile
angular.forEach
und die EingeborenenforEach
sind beide so viel langsamer als die normalefor
Schleife ... ungefähr 90% langsamer . Bei großen Datenmengen sollten Sie sich am besten an die native Datenmenge haltenfor
Schleife.continue
wird tatsächlich durch " Unfall " unterstützt, um fortzufahren, indemangular.forEach
Sie einfach einereturn;
Anweisung in die Funktion einfügen,angular.forEach(array, function(item) { if (someConditionIsTrue) return; });
die dazu führt, dass die Funktion für diese Iteration fortgesetzt wird. Dies liegt auch an der Tatsache, dass der NativeforEach
weder break unterstützt noch fortfährt.Ich bin mir sicher, dass es noch verschiedene andere Vor- und Nachteile gibt, und Sie können gerne alle hinzufügen, die Sie für richtig halten. Ich bin der Meinung, dass Sie, wenn Sie Effizienz benötigen, nur die native
for
Schleife für Ihre Schleifenanforderungen verwenden müssen. Aber wenn Ihre Datensätze kleiner sind und eine gewisse Effizienz in Ordnung ist, um im Austausch für Lesbarkeit und Schreibbarkeit aufzugeben, dann werfen Sie auf jeden Fall einenangular.forEach
in diesen bösen Jungen.quelle
Wenn es Ihnen nichts ausmacht, das Array zu leeren:
x
enthält den letzten Wert vony
und wird aus dem Array entfernt. Sie können auch verwendenshift()
, um das erste Element zu geben und zu entferneny
.quelle
[1, 2, undefined, 3]
.[1, 2, 0, 3]
oder[true, true, false, true]
Eine forEach- Implementierung ( siehe in jsFiddle ):
quelle
Wahrscheinlich ist die
for(i = 0; i < array.length; i++)
Schleife nicht die beste Wahl. Warum? Wenn Sie dies haben:Die Methode ruft von
array[0]
bis aufarray[2]
. Erstens werden zuerst Variablen referenziert, die Sie nicht einmal haben, zweitens würden Sie die Variablen nicht im Array haben, und drittens wird der Code dadurch mutiger. Schau her, es ist was ich benutze:Und wenn Sie möchten, dass es eine Funktion ist, können Sie dies tun:
Wenn Sie brechen wollen, etwas mehr Logik:
Beispiel:
Es gibt zurück:
quelle
Es gibt drei Implementierungen
foreach
in jQuery wie folgt.quelle
Ab ECMAScript 6:
Wobei
of
die damit verbundenen Kuriositäten vermieden werdenin
und es wie diefor
Schleife einer anderen Sprache funktioniert undlet
bindeti
innerhalb der Schleife im Gegensatz zu innerhalb der Funktion.Die geschweiften Klammern (
{}
) können weggelassen werden, wenn nur ein Befehl vorhanden ist (z. B. im obigen Beispiel).quelle
Eine einfache Lösung wäre jetzt die Verwendung der Bibliothek underscore.js . Es bietet viele nützliche Tools, z. B.
each
und delegiert den Job automatisch an den Native,forEach
falls verfügbar.Ein CodePen-Beispiel für die Funktionsweise ist:
Siehe auch
Array.prototype.forEach()
.for each (variable in object)
als Teil des ECMA-357 ( EAX ) -Standards veraltet ist .for (variable of object)
als Teil des Harmony-Vorschlags (ECMAScript 6).quelle
for each
In nativem JavaScript gibt es keine Schleife . Sie können entweder Bibliotheken verwenden, um diese Funktionalität zu erhalten (ich empfehle Underscore.js ), oder eine einfachefor
In-Schleife verwenden.Beachten Sie jedoch, dass es Gründe geben kann, eine noch einfachere
for
Schleife zu verwenden (siehe Frage zum Stapelüberlauf Warum ist die Verwendung von „for… in“ mit Array-Iteration eine so schlechte Idee? )quelle
Dies ist ein Iterator für eine nicht spärliche Liste, bei der der Index bei 0 beginnt. Dies ist das typische Szenario beim Umgang mit document.getElementsByTagName oder document.querySelectorAll.
Anwendungsbeispiele:
Beispiel 1
Beispiel 2
Jedes p-Tag wird erhalten
class="blue"
Beispiel 3
Jedes zweite p-Tag erhält
class="red"
>Beispiel 4
Und schließlich werden die ersten 20 blauen p-Tags in grün geändert
Vorsicht bei der Verwendung von Zeichenfolgen als Funktion: Die Funktion wird außerhalb des Kontexts erstellt und sollte nur verwendet werden, wenn Sie sich des variablen Bereichs sicher sind. Andernfalls ist es besser, Funktionen zu übergeben, bei denen das Scoping intuitiver ist.
quelle
Es gibt einige Möglichkeiten , ein Array in JavaScript zu durchlaufen:
für - es ist das häufigste . Vollständiger Codeblock für die Schleife
while - Schleife, während eine Bedingung durch ist. Es scheint die schnellste Schleife zu sein
do / while - Durchläuft auch einen Codeblock, während die Bedingung erfüllt ist, und wird mindestens einmal ausgeführt
Funktionsschleifen -
forEach
,map
,filter
, auchreduce
(sie Schleife durch die Funktion, aber sie verwendet werden , wenn Sie etwas mit Ihrem Array tun müssen, usw.Weitere Informationen und Beispiele zur funktionalen Programmierung auf Arrays finden Sie im Blogbeitrag Funktionale Programmierung in JavaScript: Zuordnen, Filtern und Reduzieren .
quelle
forEach
ist keine "funktionale" Schleife, da sie keine neueArray
zurückgibt (eigentlich gibt sie nichts zurück), sondern nur iteriert.ECMAScript 5 (die Version auf JavaScript) für die Arbeit mit Arrays:
forEach - Durchläuft jedes Element im Array und macht mit jedem Element alles, was Sie brauchen.
Falls Sie sich mehr für den Betrieb eines Arrays mit einer eingebauten Funktion interessieren.
map - Erstellt ein neues Array mit dem Ergebnis der Rückruffunktion. Diese Methode eignet sich gut, wenn Sie die Elemente Ihres Arrays formatieren müssen.
reduzieren - Wie der Name schon sagt, wird das Array auf einen einzelnen Wert reduziert, indem die angegebene Funktion aufgerufen wird, die das aktuelle Element und das Ergebnis der vorherigen Ausführung übergibt.
every - Gibt true oder false zurück, wenn alle Elemente im Array den Test in der Rückruffunktion bestehen.
filter - Sehr ähnlich zu allen, außer dass der Filter ein Array mit den Elementen zurückgibt, die für die angegebene Funktion true zurückgeben.
quelle
Es gibt keine eingebaute Fähigkeit, einzubrechen
forEach
. Um die Ausführung zu unterbrechen, gehen SieArray#some
wie folgt vor:Dies funktioniert, weil
some
true zurückgegeben wird, sobald einer der in Array-Reihenfolge ausgeführten Rückrufe true zurückgibt und die Ausführung des Restes kurzschließt. Ursprüngliche Antwort siehe Array-Prototyp für einigequelle
Ich möchte dies auch als Komposition einer Rückwärtsschleife und als Antwort oben für jemanden hinzufügen, der diese Syntax ebenfalls möchte.
Vorteile:
Der Vorteil dafür: Sie haben die Referenz bereits in der ersten, so dass sie später nicht mit einer anderen Zeile deklariert werden muss. Dies ist praktisch, wenn Sie das Objektarray durchlaufen.
Nachteile:
Dies wird immer dann unterbrochen, wenn die Referenz falsch ist - Falsey (undefiniert usw.). Es kann jedoch als Vorteil genutzt werden. Es würde jedoch das Lesen etwas erschweren. Und je nach Browser kann es "nicht" optimiert werden, um schneller als das Original zu arbeiten.
quelle
jQuery Weg mit
$.map
:quelle
[undefined, 2, undefined, 4, undefined, 6, undefined]
.Verwenden von Schleifen mit ECMAScript 6- Destrukturierung und dem Spread-Operator
Die Destrukturierung und Verwendung des Spread-Operators hat sich für Neulinge in ECMAScript 6 als sehr gut lesbar / ästhetisch erwiesen, obwohl einige JavaScript-Veteranen dies möglicherweise als chaotisch betrachten. Junioren oder andere Leute könnten es nützlich finden.
Beispiel 1: Normale
for...of
Schleife - hier keine Tricks.Beispiel 2: Wörter in Zeichen teilen
Beispiel 3: Schleifen mit einem
key
undvalue
Beispiel 4: Inline-Objekteigenschaften abrufen
Beispiel 5: Holen Sie sich tiefe Objekteigenschaften von dem, was Sie brauchen
Beispiel 6: Wird Beispiel 3 verwendet mit
.forEach
Beispiel 7: Wird Beispiel 4 verwendet mit
.forEach
Beispiel 8: Wird Beispiel 5 verwendet mit
.forEach
quelle
Ein Weg, der Ihrer Idee am nächsten kommt, wäre die Verwendung
Array.forEach()
einer Schließfunktion, die für jedes Element des Arrays ausgeführt wird.Ein anderer praktikabler Weg wäre die Verwendung,
Array.map()
die auf die gleiche Weise funktioniert, aber auch alle Werte, die Sie zurückgeben, in einem neuen Array zurückgibt (im Wesentlichen jedes Element einem neuen zuzuordnen), wie folgt:quelle
map
mutiert die Elemente des Arrays nicht, da ein neues Array zurückgegeben wird, wobei die Elemente dieses neuen Arrays das Ergebnis der Anwendung der Funktion auf die Elemente des alten Arrays sind.Sie können forEach so anrufen:
forEach
iteriert über das von Ihnen bereitgestellte Array und für jede Iteration,element
die den Wert dieser Iteration enthält. Wenn Sie einen Index benötigen, können Sie den aktuellen Index erhalten, indem Sie den übergebeni
als zweiten Parameter in der Rückruffunktion für forEach übergeben.Foreach ist im Grunde eine Funktion hoher Ordnung, die eine andere Funktion als Parameter verwendet.
Ausgabe:
Sie können auch über ein Array wie folgt iterieren:
quelle
Wenn Sie ein Array von Objekten mit der Pfeilfunktion durchlaufen möchten:
quelle
Die Lambda-Syntax funktioniert normalerweise nicht in Internet Explorer 10 oder niedriger.
Ich benutze normalerweise die
Wenn Sie ein jQuery- Fan sind und bereits eine jQuery-Datei ausgeführt wird, sollten Sie die Positionen der Index- und Wertparameter umkehren
quelle
Wenn Sie ein massives Array haben, sollten Sie es verwenden
iterators
, um eine gewisse Effizienz zu erzielen. Iteratoren ist eine Eigenschaft bestimmter JavaScript Sammlungen (wieMap
,Set
,String
,Array
). Auchfor..of
verwendetiterator
unter der Haube.Iteratoren verbessern die Effizienz, indem Sie die Elemente in einer Liste einzeln als Stream verwenden können. Das Besondere an einem Iterator ist, wie er eine Sammlung durchläuft. Andere Schleifen müssen die gesamte Sammlung im Voraus laden, um sie zu durchlaufen, während ein Iterator nur die aktuelle Position in der Sammlung kennen muss.
Sie greifen auf das aktuelle Element zu, indem Sie die
next
Methode des Iterators aufrufen . Die nächste Methode gibtvalue
das aktuelle Element und a zurück,boolean
um anzuzeigen, wann Sie das Ende der Sammlung erreicht haben. Das folgende Beispiel zeigt das Erstellen eines Iterators aus einem Array.Verwandeln Sie Ihr reguläres Array mit der folgenden
values()
Methode in einen Iterator :Sie können Ihr reguläres Array auch folgendermaßen in einen Iterator umwandeln
Symbol.iterator
:Sie können Ihren Stammkunden auch
array
in eineniterator
solchen verwandeln :HINWEIS :
iterable
standardmäßig. Verwenden Siefor..in
in diesem Fall , weil anstelle von Werten , die sie mit den Tasten funktionieren.Sie können mehr über lesen
iteration protocol
hier .quelle
Wenn Sie verwenden möchten
forEach()
, sieht es so aus:Wenn Sie verwenden möchten
for()
, sieht es so aus:quelle
Gemäß der neuen aktualisierten Funktion ECMAScript 6 (ES6) und ECMAScript 2015 können Sie die folgenden Optionen mit Schleifen verwenden:
quelle
Performance
Heute (2019.12.18) Ich führe Test auf meinem macOS v10.13.6 (High Sierra), auf Chrome v 79.0, Safari v13.0.4 und Firefox v71.0 (64 bit) - Schlussfolgerungen über Optimierung (und Mikro-Optimierung der Normalerweise lohnt es sich nicht, es in den Code einzuführen, da der Nutzen gering ist, aber die Komplexität des Codes zunimmt.
Es sieht so aus, als ob das traditionelle
for i
( Aa ) eine gute Wahl ist, um schnellen Code in allen Browsern zu schreiben.Die anderen Lösungen wie
for-of
( Ad ), alle in Gruppe C. ... sind normalerweise 2 bis 10 (und mehr) Mal langsamer als Aa , aber für kleine Arrays ist es in Ordnung, sie zu verwenden - um die Klarheit des Codes zu erhöhen.Die in
n
( Ab, Bb, Be ) zwischengespeicherten Schleifen mit Array-Länge sind manchmal schneller, manchmal nicht. Wahrscheinlich erkennen Compiler diese Situation automatisch und führen das Caching ein. Die Geschwindigkeitsunterschiede zwischen der zwischengespeicherten und der nicht zwischengespeicherten Version ( Aa, Ba, Bd ) betragen etwa ~ 1%. Es sieht also so aus, als wäre einführenn
eine Mikrooptimierung .Die
i--
wie Lösungen , wo die Schleife beginnt mit dem letzten Array - Elemente ( Ac, Bc ) sind in der Regel ca. 30% langsamer als Vorwärts-Lösungen - wahrscheinlich der Grund dafür ist die Art und Weise der CPU - Speicher - Cache Arbeits - Vorwärts-Speicher Lesen ist optimal für die CPU - Caching). Es wird empfohlen, solche Lösungen NICHT zu verwenden.Einzelheiten
In Tests berechnen wir die Summe der Array-Elemente. Ich führe einen Test für kleine Arrays (10 Elemente) und große Arrays (1M Elemente) durch und teile sie in drei Gruppen ein:
for
Testswhile
TestsCode-Snippet anzeigen
Browserübergreifende Ergebnisse
Ergebnisse für alle getesteten Browser
Browser **
Array mit 10 Elementen
Ergebnisse für Chrome. Sie können den Test auf Ihrem Rechner ausführen hier .
Array mit 1.000.000 Elementen
Ergebnisse für Chrome. Sie können den Test auf Ihrem Rechner ausführen hier
quelle
Zusammenfassung:
Wenn wir über ein Array iterieren, möchten wir häufig eines der folgenden Ziele erreichen:
Wir möchten das Array durchlaufen und ein neues Array erstellen:
Array.prototype.map
Wir möchten das Array durchlaufen und kein neues Array erstellen:
Array.prototype.forEach
for..of
SchleifeIn JavaScript gibt es viele Möglichkeiten, diese beiden Ziele zu erreichen. Einige sind jedoch bequemer als andere. Im Folgenden finden Sie einige häufig verwendete Methoden (die bequemste IMO), um die Array-Iteration in JavaScript durchzuführen.
Neues Array erstellen:
Map
map()
ist eine Funktion, mitArray.prototype
der jedes Element eines Arrays transformiert und dann ein neues Array zurückgegeben werden kann.map()
Nimmt als Argument eine Rückruffunktion und funktioniert folgendermaßen:Der Rückruf, den wir
map()
als Argument übergeben haben, wird für jedes Element ausgeführt. Dann wird ein Array zurückgegeben, das dieselbe Länge wie das ursprüngliche Array hat. In diesem neuen Array wird das Element durch die Rückruffunktion transformiert, die als Argument an übergeben wirdmap()
.Der deutliche Unterschied zwischen
map
einem anderen Schleifenmechanismus wieforEach
und einerfor..of
Schleife besteht darin, dassmap
ein neues Array zurückgegeben wird und das alte Array intakt bleibt (es sei denn, Sie manipulieren es explizit mit "think like"splice
).Beachten Sie außerdem, dass der
map
Rückruf der Funktion die Indexnummer der aktuellen Iteration als zweites Argument bereitstellt. Gibt das dritte Argument außerdem das Array an, auf demmap
aufgerufen wurde? Manchmal können diese Eigenschaften sehr nützlich sein.Schleife mit
forEach
forEach
ist eine Funktion, die sich befindet undArray.prototype
eine Rückruffunktion als Argument verwendet. Diese Rückruffunktion wird dann für jedes Element im Array ausgeführt. Im Gegensatz zurmap()
Funktion gibt die Funktion forEach nichts zurück (undefined
). Zum Beispiel:Genau wie die
map
FunktionforEach
liefert der Rückruf die Indexnummer der aktuellen Iteration als zweites Argument. Gibt das dritte Argument auch das Array an, für dasforEach
aufgerufen wurde?Durchlaufen Sie Elemente mit
for..of
Die
for..of
Schleife durchläuft jedes Element eines Arrays (oder eines anderen iterierbaren Objekts). Es funktioniert folgendermaßen:Im obigen Beispiel
element
steht für ein Array-Element undarr
ist das Array, das wir schleifen möchten. Beachten Sie, dass der Nameelement
willkürlich ist und wir einen anderen Namen wie 'el' oder etwas aussagekräftigeres wählen könnten, wenn dies zutreffend ist.Verwechseln Sie die
for..in
Schleife nicht mit derfor..of
Schleife.for..in
Durchläuft alle aufzählbaren Eigenschaften des Arrays, während diefor..of
Schleife nur die Array-Elemente durchläuft. Zum Beispiel:quelle