Durchlaufen Sie ein Array in JavaScript


3145

In Java können Sie eine forSchleife verwenden, um Objekte in einem Array wie folgt zu durchlaufen:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

Können Sie dasselbe in JavaScript tun?


5
Ok, ich bin ein bisschen verwirrt. Ist es in Ordnung, die erweiterte for-Schleife zu verwenden, wenn Sie auf die Objekte zugreifen? Und eine sequentielle zum Füllen verwenden? Ist das richtig?
Mark Szymanski

45
nein, es ist wirklich einfach, Array - Objekte numerische Indizes, so dass Sie zu wollen , durchlaufen diese Indizes in der numerischen Reihenfolge, eine sequentielle Schleife sorgt über die, die verbesserte for-in Schleife zählt auf Objekteigenschaften, ohne eine bestimmte Reihenfolge, und es zählt auch vererbten Eigenschaften. .. für die Iteration über Arrays werden immer sequentielle Schleifen empfohlen ...
CMS


6
jsben.ch/#/Q9oD5 <= Hier ein Benchmark einer Reihe von Lösungen für das Durchlaufen von Arrays
EscapeNetscape

3
@CMS Nein, es ist nicht wirklich einfach. In jeder anderen Sprache ist es wirklich einfach. Es ist lächerlich komplex in JS, wo Sie haben inund ofdas kann sowohl verwendet werden als auch verschiedene Dinge tun. Dann haben Sie auch forEachund die hässliche und nervige indexbasierte Schleife. Jede andere moderne Sprache macht das Durchlaufen einer Sammlung einfach und unkompliziert, ohne Überraschungen oder Verwirrung. JS könnte es auch, aber das tut es nicht.
jpmc26

Antworten:


3961

Sie haben mehrere Möglichkeiten:

1. Sequenzschleife for:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    console.log(myStringArray[i]);
    //Do something
}

Vorteile

  • Funktioniert in jeder Umgebung
  • Sie können Steueranweisungen verwenden breakund continuesteuern

Nachteile

  • Zu ausführlich
  • Imperativ
  • Einfache Fehler nacheinander (manchmal auch als Zaunpfostenfehler bezeichnet )

2. Array.prototype.forEach

Die ES5-Spezifikation führte viele nützliche Array-Methoden ein, eine davon, Array.prototype.forEachund bietet uns eine präzise Möglichkeit, über ein Array zu iterieren:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

Vor fast zehn Jahren, als die ES5-Spezifikation veröffentlicht wurde (Dezember 2009), wurde sie von fast allen modernen Engines in Desktop-, Server- und Mobilumgebungen implementiert, sodass ihre Verwendung sicher ist.

Und mit der Syntax der ES6-Pfeilfunktion ist es noch prägnanter:

array.forEach(item => console.log(item));

Pfeilfunktionen sind ebenfalls weit verbreitet, es sei denn, Sie möchten alte Plattformen (z. B. IE11) unterstützen. Sie sind auch sicher zu gehen.

Vorteile

  • Sehr kurz und prägnant.
  • Deklarativ

Nachteile

  • Kann break/ nicht verwendencontinue

Normalerweise können Sie die Notwendigkeit ersetzen break, imperative Schleifen zu verlassen, indem Sie die Array-Elemente filtern, bevor Sie sie iterieren. Beispiel:

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

Denken Sie daran, wenn Sie ein Array iterieren , um ein anderes Array daraus zu erstellen , sollten Sie es verwenden map. Ich habe dieses Anti-Pattern so oft gesehen.

Anti-Muster:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

Richtiger Anwendungsfall der Karte :

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

Wenn Sie versuchen, das Array auf einen Wert zu reduzieren , z. B. ein Array von Zahlen summieren möchten, sollten Sie die Reduktionsmethode verwenden.

Anti-Muster:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

Richtige Verwendung von reduzieren :

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. ES6- for-ofAnweisung

Der ES6-Standard führt das Konzept iterierbarer Objekte ein und definiert ein neues Konstrukt zum Durchlaufen von Daten, die for...ofAnweisung.

Diese Anweisung funktioniert für jede Art von iterierbarem Objekt und auch für Generatoren (jedes Objekt, das eine [Symbol.iterator]Eigenschaft hat).

Array-Objekte sind per Definition in ES6 integrierte Iterables, sodass Sie diese Anweisung für sie verwenden können:

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

Vorteile

  • Es kann über eine Vielzahl von Objekten iterieren.
  • Kann normale Flusskontrollanweisungen ( break/ continue) verwenden.
  • Nützlich, um seriell asynchrone Werte zu iterieren.

Nachteile

  • Wenn Sie auf ältere Browser abzielen, kann Sie die transpilierte Ausgabe überraschen .

Verwende nicht for...in

@zipcodeman schlägt die Verwendung der for...inAussage, aber Arrays zur Iteration for-insollte vermieden werden, wird diese Aussage gemeint enumerate Objekteigenschaften.

Es sollte nicht für Array-ähnliche Objekte verwendet werden, weil:

  • Die Reihenfolge der Iteration ist nicht garantiert. Die Array-Indizes dürfen nicht in numerischer Reihenfolge besucht werden.
  • Vererbte Eigenschaften werden ebenfalls aufgelistet.

Der zweite Punkt ist, dass es Ihnen viele Probleme bereiten kann. Wenn Sie beispielsweise das Array.prototypeObjekt um eine Methode erweitern, wird diese Eigenschaft ebenfalls aufgelistet.

Zum Beispiel:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
    console.log(array[i]);
}

Der obige Code konsolidiert das Protokoll "a", "b", "c" und "foo!".

Dies ist insbesondere dann ein Problem, wenn Sie eine Bibliothek verwenden, die stark auf der Erweiterung nativer Prototypen basiert (z. B. MooTools).

Die for-inErklärung , wie ich sagte , bevor es aufzuzählen Objekteigenschaften, zum Beispiel:

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) { 
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

Im obigen Beispiel hasOwnPropertykönnen Sie mit der Methode nur eigene Eigenschaften auflisten, dh nur die Eigenschaften, über die das Objekt physisch verfügt, keine geerbten Eigenschaften.

Ich würde Ihnen empfehlen, den folgenden Artikel zu lesen:


21
Dies ist der Grund (von CMS selbst) stackoverflow.com/questions/1885317/…
OscarRyz

15
@DoubleGras, ich denke, das ist eine Meinung, die nicht von allen geteilt wird. Siehe: stackoverflow.com/questions/5752906/… oder groups.google.com/forum/?fromgroups#!topic/jsmentors/…
Matthijs Wessels

3
Jeder, der denkt, Sie müssen die Länge zwischenspeichern ... Bitte beachten Sie meine Antwort, Sie müssen nicht einmal darauf zugreifen, geschweige denn darauf zwischenspeichern: for (var i = 0, item; item = myStringArray [i]; i ++) {/ * Artikel hier verwenden * /}
Stijn de Witt

15
@StijndeWitt Nein, denn das bricht , wenn Sie irgendwelche „Falsey“ Werte im Array: false, undefined, 0, "", NaN.
Phrogz

6
jsperf.com/caching-array-length/4 Hier ist ein Test, um festzustellen , ob es sich lohnt, die Länge eines Arrays in einer Javascript-Schleife zwischenzuspeichern
Enrico

1114

Ja, vorausgesetzt, Ihre Implementierung enthält die in ECMAScript 2015 eingeführte Funktion for...of (die "Harmony" -Version) ..., was heutzutage eine ziemlich sichere Annahme ist.

Es funktioniert so:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

Oder noch besser, da ECMAScript 2015 auch Variablen mit Blockbereich bietet:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

(Die Variable sist bei jeder Iteration unterschiedlich, kann jedoch constinnerhalb des Schleifenkörpers deklariert werden, solange sie dort nicht geändert wird.)

Ein Hinweis zu spärlichen Arrays: Ein Array in JavaScript speichert möglicherweise nicht so viele Elemente, wie von seinem gemeldet werden length. Diese gemeldete Zahl ist einfach eins größer als der höchste Index, bei dem ein Wert gespeichert wird. Wenn das Array weniger Elemente enthält als durch seine Länge angegeben, wird es als spärlich bezeichnet . Zum Beispiel ist es absolut legitim, ein Array mit Elementen nur in den Indizes 3, 12 und 247 zu haben. das s für fehlende Elemente, oder möchten Sie nur die tatsächlich vorhandenen Elemente verarbeiten? Es gibt viele Anwendungen für beide Ansätze; Es hängt nur davon ab, wofür Sie das Array verwenden.length eines solchen Arrays wird als 248 gemeldet, obwohl es tatsächlich nur 3 Werte speichert. Wenn Sie versuchen, auf ein Element in einem anderen Index zuzugreifen, scheint das Array dort den undefinedWert zu haben. Wenn Sie also ein Array "durchlaufen" möchten, müssen Sie eine Frage beantworten: Möchten Sie den gesamten Bereich durchlaufen, der durch seine Länge und seinen Prozess angezeigt wird?undefined

Wenn Sie ein Array mit for.. durchlaufen of, wird der Hauptteil der Schleife lengthmal ausgeführt , und die Regelungsvariable undefinedfür alle Elemente, die nicht im Array vorhanden sind, wird auf gesetzt. Abhängig von den Details Ihres Codes "Mach etwas mit" kann dieses Verhalten das sein, was Sie wollen, aber wenn nicht, sollten Sie einen anderen Ansatz verwenden.

Natürlich haben einige Entwickler keine andere Wahl, einen anderen Ansatz zu verwenden , wie auch immer, weil aus irgendeinem Grund sie eine Version von JavaScript Targeting sind , die noch nicht unterstützt for... of.

Solange Ihre JavaScript-Implementierung mit der vorherigen Ausgabe der ECMAScript-Spezifikation kompatibel ist (die beispielsweise Versionen von Internet Explorer vor 9 ausschließt), können Sie die Array#forEachIteratormethode anstelle einer Schleife verwenden. In diesem Fall übergeben Sie eine Funktion, die für jedes Element im Array aufgerufen werden soll:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

Im Gegensatz zu for... ofwird .forEachdie Funktion nur für Elemente aufgerufen, die tatsächlich im Array vorhanden sind. Wenn unser hypothetisches Array mit drei Elementen und einer Länge von 248 übergeben wird, wird die Funktion nur dreimal aufgerufen, nicht 248 Mal. Es wird auch zwischen fehlenden Elementen und Elementen unterschieden, die tatsächlich eingestellt sind undefined. Für letzteres wird die Funktion weiterhin aufgerufen und undefinedals Argument übergeben. Wenn Sie auf diese Weise mit spärlichen Arrays umgehen möchten, ist dies .forEachmöglicherweise der richtige Weg, auch wenn Ihr Interpreter for... unterstützt of.

Die letzte Option, die in allen Versionen von JavaScript funktioniert , ist eine explizite Zählschleife . Sie zählen einfach von 0 bis eins weniger als die Länge und verwenden den Zähler als Index. Die Grundschleife sieht folgendermaßen aus:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

Ein Vorteil dieses Ansatzes besteht darin, dass Sie auswählen können, wie mit spärlichen Arrays umgegangen werden soll. Der obige Code wird den Körper der Schleife der vollen läuft lengthmal mit sSatz undefinedfür alle fehlenden Elemente, wie for.. of. Wenn Sie stattdessen nur die tatsächlich vorhandenen Elemente eines spärlichen Arrays behandeln möchten .forEach, können Sie indem Index einen einfachen Test hinzufügen :

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Das Zuweisen des Längenwerts zur lokalen Variablen (im Gegensatz zum Einfügen des vollständigen myStringArray.lengthAusdrucks in die Schleifenbedingung) kann einen erheblichen Leistungsunterschied bewirken, da jedes Mal eine Eigenschaftssuche übersprungen wird. Wenn ich Rhino auf meinem Computer verwende, beträgt die Beschleunigung 43%.

Möglicherweise sehen Sie das Längen-Caching in der Schleifeninitialisierungsklausel wie folgt:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

Die explizite Zählschleife bedeutet auch, dass Sie auf den Index jedes Werts zugreifen können, falls Sie dies wünschen. Der Index wird auch als zusätzlicher Parameter an die Funktion übergeben forEach, an die Sie übergeben , sodass Sie auch auf diese Weise darauf zugreifen können:

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for... ofgibt Ihnen nicht den Index an, der jedem Objekt zugeordnet ist, aber solange das Objekt, über das Sie iterieren, tatsächlich ein Objekt ist Array( for.. offunktioniert für andere iterierbare Typen, die diese Methode möglicherweise nicht haben), können Sie das Array verwenden #entries- Methode, um sie in ein Array von [index, item] -Paaren zu ändern und dann darüber zu iterieren:

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

Das forin von anderen erwähnte ... -Syntax dient zum Durchlaufen der Eigenschaften eines Objekts. Da ein Array in JavaScript nur ein Objekt mit numerischen Eigenschaftsnamen (und einer automatisch aktualisierten lengthEigenschaft) ist, können Sie theoretisch ein Array damit durchlaufen. Das Problem ist jedoch, dass es sich nicht auf die numerischen Eigenschaftswerte beschränkt (denken Sie daran, dass selbst Methoden eigentlich nur Eigenschaften sind, deren Wert ein Abschluss ist), und es wird auch nicht garantiert, dass es über diese in numerischer Reihenfolge iteriert. Daher sollte die for... in-Syntax nicht zum Durchlaufen von Arrays verwendet werden.


21
Beachten Sie, dass einige Interpreter (z. B. V8) die Länge des Arrays automatisch zwischenspeichern, wenn der Code genügend oft aufgerufen wird und festgestellt wird, dass die Länge von der Schleife nicht geändert wird. Das Zwischenspeichern der Länge ist zwar immer noch hilfreich, bietet jedoch möglicherweise keinen Geschwindigkeitsschub, wenn Ihr Code genügend oft aufgerufen wird, um tatsächlich einen Unterschied zu bewirken.
Phrogz

2
@ mark-reed Könnten Sie bitte erklären, warum Sie i in myStringArrayin Ihrem Beispiel verwendet haben? Wie kann das falsch sein?
Denis V

2
@DenisV: falsch. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); } Ausgänge 0, 1, 3 und 4. a.lengthist immer noch 5.
Mark Reed

1
Ich schlage nicht vor for j in a. Ich demonstriere, dass die inPrüfung nicht redundant ist, wie Sie behauptet haben, indem ich alle Indizes zeige und zeige, dass es einen zwischen 0 gibt und length-1dieser nicht da ist. Ich hätte auch einfach drucken können 2 in a, was in der Tat der Fall ist false, obwohl Sie sagten, dass dies unmöglich sei.
Mark Reed

2
@GrijeshChauhan - richtig. Zum Beispiel unterstützt IE bis Version 8 dies nicht. Siehe diese Frage .
Mark Reed

442

Sie können mapeine funktionale Programmiertechnik verwenden, die auch in anderen Sprachen wie Python und Haskell verfügbar ist .

[1,2,3,4].map( function(item) {
     alert(item);
})

Die allgemeine Syntax lautet:

array.map(func)

Im Allgemeinen funcwürde ein Parameter verwendet, der ein Element des Arrays ist. Im Fall von JavaScript kann jedoch ein zweiter Parameter, der der Index des Elements ist, und ein dritter Parameter, der das Array selbst ist, verwendet werden.

Der Rückgabewert von array.mapist ein anderes Array, sodass Sie es folgendermaßen verwenden können:

var x = [1,2,3,4].map( function(item) {return item * 10;});

Und jetzt ist x [10,20,30,40].

Sie müssen die Funktion nicht inline schreiben. Es könnte eine separate Funktion sein.

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

das wäre eine Art Äquivalent zu:

 for (item in my_list) {item_processor(item);}

Außer du verstehst das nicht new_list.


7
Nein, aber es kann mächtiger sein. Check this out: joelonsoftware.com/items/2006/08/01.html
hasen

97
Dieses spezielle Beispiel wird wahrscheinlich besser mit implementiert Array.forEach. mapdient zum Generieren eines neuen Arrays.
Harto

21
@hasen, die Array.prototype.mapMethode ist Teil des ECMAScript 5th Edition Standard, ist noch nicht in allen Implementierungen verfügbar (z. B. IE fehlt), auch zum Iterieren über ein Array. Ich denke, die Array.prototype.forEachMethode ist semantisch korrekter. Ich schlage die For-In-Erklärung vor, siehe meine Antwort für weitere Details :)
CMS

3
Der Unterschied zwischen forEachund mapbesteht darin, dass Ersteres die Ergebnisse der Iteration nicht zurückgibt. map(manchmal auch bekannt collect, aber sehr verschieden von apply) dient ausdrücklich dazu, jedes Element eines Arrays in ein entsprechendes Ergebnis umzuwandeln. Es ist eine 1-zu-1- Zuordnung , daher der Name. Es ist Teil einer ganzen Familie von Operationen, reducedie Folgendes umfassen (was ein einzelnes Ergebnis aus dem gesamten Array erzeugt) und filter(was eine Teilmenge des ursprünglichen Arrays erzeugt) und so weiter. Während forEachmit jedem Element nur etwas zu tun ist, ist die Semantik nicht spezifiziert.
Mark Reed

4
Downvote, denn wenn Sie nicht wirklich etwas zuordnen, ist die Verwendung von [] .map irreführend. [] .forEach ist semantisch sinnvoll und übergibt die gleichen drei Argumente an die Funktion.
Gengkev

120

In JavaScript ist es nicht ratsam, ein Array mit einer For-In-Schleife zu durchlaufen, aber es ist besser, eine forSchleife zu verwenden , z.

for(var i=0, len=myArray.length; i < len; i++){}

Es ist ebenfalls optimiert ("Caching" der Array-Länge). Wenn Sie mehr erfahren möchten, lesen Sie meinen Beitrag zu diesem Thema .


2
myArray.forEach (function (obj) {}); ist immer noch das Beste
Jan Sverre

eine winzige Verbesserung: Sie könnten ++ianstelle voni++
Roberkules

14
++iist eine Old-School-Optimierung, die moderne Compiler seit langer Zeit in einer for-Schleife für Sie durchführen :) stackoverflow.com/a/1547433/1033348
ngryman

6
Sie müssen vorsichtig sein, wenn Sie diese Schleife verwenden. Ich habe damit angefangen und hatte aufgrund eines Fehlers, den ich gemacht habe, einen schwer zu verfolgenden Fehler. Wenn Sie zwei Schleifen wie folgt verschachteln : jsfiddle.net/KQwmL/1 . Sie müssen darauf achten, die Variable in den beiden Schleifen unterschiedlich zu benennen, da sonst die zweite Schleife die erste Länge überschreibt.
Rui Marques

1
Rui Marques - Sie können Ihre Variable benennen i_stopoder i_endstattdessen len. Es ist genauso lesbar (wenn nicht mehr!), Und Sie werden diese Art von Problem natürlich vermeiden (da Ihre andere Schleife z j_stop. B. wird ).
Chip Hogg

119

für (lass uns von myStringArray) {

(Beantworten Sie Ihre Frage direkt: Jetzt können Sie!)

Die meisten anderen Antworten sind richtig, aber sie erwähnen (zum Zeitpunkt dieses Schreibens) nicht, dass ECMA Script  6  2015 einen neuen Mechanismus für die Iteration bringt, die for..ofSchleife.

Diese neue Syntax ist die eleganteste Methode, um ein Array in Javascript zu iterieren (solange Sie den Iterationsindex nicht benötigen).

Es funktioniert derzeit mit Firefox 13+, Chrome 37+ und nicht nativ mit anderen Browsern (siehe Browserkompatibilität unten). Glücklicherweise haben wir JS-Compiler (wie Babel ), mit denen wir heute Funktionen der nächsten Generation verwenden können.

Es funktioniert auch auf Node (ich habe es auf Version 0.12.0 getestet).

Iterieren eines Arrays

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Iterieren einer Reihe von Objekten

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Iterieren eines Generators:

(Beispiel aus https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of )

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Kompatibilitätstabelle: http://kangax.github.io/es5-compat-table/es6/#For..of Schleifen

Spezifikation: http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}}


Wenn Sie ES6 verwenden, würde ich const sanstelle vonvar s
joeytwiddle

In meinen Tests mit großen Arrays var s of arrist die Ausführungszeit fast doppelt so hoch (1,9x) wie die Verwendung eines einfachen Zählers für die Schleife und das Abrufen von Elementen nach Index in nodejs
theferrit32

Warum dieses seltsame Zeug in der ersten und letzten Zeile?
Peter Mortensen

91

Opera, Safari, Firefox und Chrome verwenden jetzt eine Reihe erweiterter Array-Methoden zur Optimierung vieler gängiger Schleifen.

Möglicherweise benötigen Sie nicht alle, aber sie können sehr nützlich sein, oder wenn jeder Browser sie unterstützt.

Mozilla Labs hat die von ihnen und WebKit verwendeten Algorithmen veröffentlicht , sodass Sie sie selbst hinzufügen können.

Der Filter gibt ein Array von Elementen zurück, die eine Bedingung oder einen Test erfüllen.

Jedes gibt true zurück, wenn jedes Array-Mitglied den Test besteht.

Einige geben true zurück, wenn jemand den Test besteht.

forEach führt für jedes Array-Mitglied eine Funktion aus und gibt nichts zurück.

map ist wie forEach, gibt jedoch für jedes Element ein Array der Ergebnisse der Operation zurück.

Diese Methoden verwenden alle eine Funktion für ihr erstes Argument und haben ein optionales zweites Argument. Dies ist ein Objekt, dessen Bereich Sie den Array-Mitgliedern beim Durchlaufen der Funktion auferlegen möchten.

Ignoriere es, bis du es brauchst.

indexOf und lastIndexOf finden die entsprechende Position des ersten oder letzten Elements, die genau zu seinem Argument passt.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();

1
Ergänzung: IE unterstützt forEach seit Version 9, siehe forEach-Methode MSDN
rwitzel

75

Intro

Seit meiner Zeit am College habe ich in Java, JavaScript, Pascal, ABAP programmiert , PHP, Progress 4GL, C / C ++ und möglicherweise einigen anderen Sprachen programmiert, an die ich momentan nicht denken kann.

Während sie alle ihre eigenen sprachlichen Eigenheiten haben, teilt jede dieser Sprachen viele der gleichen Grundkonzepte. Solche Konzepte umfassen Prozeduren / Funktionen, IFAnweisungen, FORSchleifen und WHILESchleifen.


Eine traditionelle forSchleife

Eine herkömmliche forSchleife besteht aus drei Komponenten:

  1. Die Initialisierung: Wird ausgeführt, bevor der Look-Block zum ersten Mal ausgeführt wird
  2. Die Bedingung: Überprüft jedes Mal eine Bedingung, bevor der Schleifenblock ausgeführt wird, und beendet die Schleife, wenn sie falsch ist
  3. Der nachträgliche Gedanke: Wird jedes Mal ausgeführt, nachdem der Schleifenblock ausgeführt wurde

Diese drei Komponenten sind durch ein ;Symbol voneinander getrennt . Der Inhalt für jede dieser drei Komponenten ist optional. Dies bedeutet, dass die folgende forSchleife so gering wie möglich ist:

for (;;) {
    // Do stuff
}

Natürlich müssen Sie ein if(condition === true) { break; } oder if(condition === true) { return; }irgendwo in diese forSchleife einfügen, damit sie nicht mehr läuft.

Normalerweise wird die Initialisierung jedoch verwendet, um einen Index zu deklarieren, die Bedingung wird verwendet, um diesen Index mit einem minimalen oder maximalen Wert zu vergleichen, und der nachträgliche Gedanke wird verwendet, um den Index zu erhöhen:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

Verwenden einer herkömmlichen forSchleife zum Durchlaufen eines Arrays

Die traditionelle Art, ein Array zu durchlaufen, ist folgende:

for (var i = 0, length = myArray.length; i < length; i++) {
    console.log(myArray[i]);
}

Wenn Sie es vorziehen, rückwärts zu schleifen, tun Sie Folgendes:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

Es sind jedoch viele Variationen möglich, wie zum Beispiel diese:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

...oder dieses...

var i = 0, length = myArray.length;
for (; i < length;) {
    console.log(myArray[i]);
    i++;
}

...oder dieses:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

Was am besten funktioniert, hängt hauptsächlich vom persönlichen Geschmack und dem spezifischen Anwendungsfall ab, den Sie implementieren.

Beachten Sie, dass jede dieser Varianten von allen Browsern unterstützt wird, auch von sehr sehr alten!


Eine whileSchleife

Eine Alternative zu einer forSchleife ist eine whileSchleife. Um ein Array zu durchlaufen, können Sie Folgendes tun:

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

Wie herkömmliche forSchleifen werden whileSchleifen auch von den ältesten Browsern unterstützt.

Beachten Sie außerdem, dass jede while-Schleife als forSchleife umgeschrieben werden kann . Zum Beispiel whileverhält sich die Schleife oben genauso wie diese forSchleife:

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...in und for...of

In JavaScript können Sie dies auch tun:

for (i in myArray) {
    console.log(myArray[i]);
}

Dies sollte jedoch mit Vorsicht angewendet werden, da es sich nicht forin allen Fällen wie eine herkömmliche Schleife verhält und potenzielle Nebenwirkungen berücksichtigt werden müssen. Siehe Warum ist die Verwendung von "for ... in" mit Array-Iteration eine schlechte Idee?für mehr Details.

Als Alternative dazu for...ingibt es jetzt auch für for...of. Das folgende Beispiel zeigt den Unterschied zwischen einer for...ofSchleife und einer for...inSchleife:

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

Darüber hinaus müssen Sie berücksichtigen, dass keine Version von Internet Explorer unterstützt for...of( Edge 12+ ) und dass for...inmindestens Internet Explorer 10 erforderlich ist.


Array.prototype.forEach()

Eine Alternative zu for-loops ist Array.prototype.forEach()die folgende Syntax:

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach() wird von allen modernen Browsern sowie von Internet Explorer 9 und höher unterstützt.


Bibliotheken

Schließlich haben viele Dienstprogrammbibliotheken auch ihre eigene foreachVariante. AFAIK, die drei beliebtesten sind:

jQuery.each(), in jQuery :

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each(), in Underscore.js :

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach(), in Lodash.js :

_.forEach(myArray, function(value, key) {
    console.log(value);
});

68

Verwenden Sie die while-Schleife ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

Protokolle: 'eins', 'zwei', 'drei'

Und für die umgekehrte Reihenfolge eine noch effizientere Schleife

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

Protokolle: 'drei', 'zwei', 'eins'

Oder die klassische forSchleife

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

Protokolle: 'eins', 'zwei', 'drei'

Referenz: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


21
Das erste Beispiel für die "while" -Syntax funktioniert nicht, wenn eines der Array-Elemente falsch ist.
Chris Cooper

2
... und diese while-Schleife entspricht: for (var i = 0, item; item = items [i]; i ++), wodurch die Notwendigkeit entfällt, die Index- und item-Variablen vorher zu deklarieren ...
Stijn de Witt


39

Wenn Sie eine knappe Methode zum Schreiben einer schnellen Schleife wünschen und umgekehrt iterieren können:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

Dies hat den Vorteil, dass die Länge zwischengespeichert wird (ähnlich for (var i=0, len=myArray.length; i<len; ++i)und nicht ähnlich for (var i=0; i<myArray.length; ++i)), während weniger Zeichen eingegeben werden müssen.

Es gibt sogar Zeiten, in denen Sie in umgekehrter Reihenfolge iterieren sollten, z. B. wenn Sie über eine Live-NodeList iterieren, in der Sie während der Iteration Elemente aus dem DOM entfernen möchten .


16
Für die Leute, die nicht verstehen, was so genial ist: Der i-- -Ausdruck wird zuerst ausgewertet und ermöglicht es der Schleife, fortzufahren, wenn sie nicht falsch ist ... Danach wird der Zähler dekrementiert. Sobald ich Null werde, bricht es aus der Schleife aus, da Null ein falscher Wert in Javascript ist.
Stijn de Witt

5
falsch? Du meinst Falsey. Lassen Sie uns alle die richtige Terminologie
einhalten

4
Ich habe gesehen, dass der Begriff Falsch von Leuten verwendet wird, die ich als Gurus betrachte. Wenn es gut genug für sie ist, ist es gut genug für mich. Auch ein, aber enttäuscht zu sehen, dass mein Kommentar, der tatsächlich ontopisch ist und Erklärung / Einsicht hinzufügt, 0 positive Stimmen erhält, aber der Kommentar, der einen Begriff in meinem Kommentar nicht auswählt, erhält 4. Ah, nur eine Frage der Prioritäten, denke ich.
Stijn de Witt

"Zwischenspeichern der Länge"? Die Länge wird als Ganzzahl im Array gespeichert und nicht jedes Mal gemessen, wenn Sie darauf zugreifen. Es hat hier keinen Vorteil, den Wert der Länge in eine andere Variable zu kopieren.
Mouscellaneous

1
@Mouscellaneous Heutzutage gibt es sicherlich nicht; In den vergangenen Jahren war das Iterieren von JavaScript-Arrays, bei denen die Länge auf der JavaScript-Seite zwischengespeichert wurde (anstatt über die Implementierung zu reichen), ein deutlicher Leistungsgewinn (bei der Mikrooptimierung). Zum Beispiel for (var i=0,len=array.length;i<len;++i)war eine übliche, sinnvolle Schleife zu schreiben.
Phrogz

36

Einige Anwendungsfälle für das Durchlaufen eines Arrays in der funktionalen Programmierweise in JavaScript:

1. Durchlaufen Sie einfach ein Array

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

Hinweis: Array.prototype.forEach () ist streng genommen keine funktionale Methode, da die Funktion, die als Eingabeparameter verwendet wird, keinen Wert zurückgeben soll, der daher nicht als reine Funktion angesehen werden kann.

2. Überprüfen Sie, ob eines der Elemente in einem Array einen Test besteht

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. In ein neues Array transformieren

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

Hinweis: Die map () -Methode erstellt ein neues Array mit den Ergebnissen des Aufrufs einer bereitgestellten Funktion für jedes Element im aufrufenden Array.

4. Fassen Sie eine bestimmte Eigenschaft zusammen und berechnen Sie ihren Durchschnitt

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. Erstellen Sie ein neues Array basierend auf dem Original, ohne es jedoch zu ändern

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6. Zählen Sie die Nummer jeder Kategorie

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. Rufen Sie eine Teilmenge eines Arrays basierend auf bestimmten Kriterien ab

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

Hinweis: Die filter () -Methode erstellt ein neues Array mit allen Elementen, die den von der bereitgestellten Funktion implementierten Test bestehen.

8. Sortieren Sie ein Array

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

Geben Sie hier die Bildbeschreibung ein

9. Suchen Sie ein Element in einem Array

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

Geben Sie hier die Bildbeschreibung ein

Die Methode Array.prototype.find () gibt den Wert des ersten Elements im Array zurück, das die bereitgestellte Testfunktion erfüllt.

Verweise


30

Es gibt eine Möglichkeit, dies zu tun, wenn Sie nur sehr wenig impliziten Bereich in Ihrer Schleife haben und zusätzliche Variablen entfernen.

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Oder wenn Sie wirklich die ID erhalten und eine wirklich klassische forSchleife haben möchten :

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Moderner Browser all Unterstützung Iteratormethoden forEach, map, reduce, filterund eine Vielzahl von anderen Methoden auf dem Array - Prototyp .


3
Beachten Sie, dass einige Interpreter (z. B. V8) die Länge des Arrays automatisch zwischenspeichern, wenn der Code genügend oft aufgerufen wird und festgestellt wird, dass die Länge von der Schleife nicht geändert wird.
Phrogz

Vielen Dank für die Info @Phrogz. Es gibt zwar viele Optimierungen, die die VM vornehmen kann, aber da ältere Browser dies nicht haben, ist es immer noch empfehlenswert, sie zu optimieren, da sie so billig ist.
Gabriel

1
@ Gabriel: Warum? Bitte geben Sie Beispiele aus der Praxis, die zeigen, dass das Nicht-Zwischenspeichern der Länge tatsächlich einen Leistungsengpass darstellt. Ich folge dem Ansatz "Vorzeitige Optimierung ist die Wurzel allen Übels". Ich werde diese eine Schleife beheben, die tatsächlich ein Problem darstellt, sobald ich darauf
Stijn de Witt

1
@StijndeWitt imo es ist nur ein stilistisches Problem. Ehrlich gesagt verwende ich nicht einmal mehr für Schleifen, sondern verlasse mich auf Unterstriche für Dinge wie _.each, _.map usw., um diese Dinge zu tun. Wenn ich solche Schleifen geschrieben habe, habe ich die Länge hauptsächlich zwischengespeichert, sodass sich alle meine Variablendeklarationen an einer Stelle oben in meiner Funktion befanden. Das Befolgen meiner diesbezüglichen Ratschläge ist für jede reale Anwendung unerheblich. Vorzeitige Optimierung ist super schlecht, aber wenn die Optimierung aus stilistischen Entscheidungen resultiert, denke ich nicht, dass es wirklich wichtig ist.
Gabriel

1
@Gabriel Ich glaube, JavaScript unterstützt bereits die Map-Funktion auf Arrays, dafür muss keine zusätzliche Bibliothek eingeführt werden.
Noz

28

Es gibt verschiedene Möglichkeiten, ein Array in JavaScript zu durchlaufen.

Generische Schleife:

var i;
for (i = 0; i < substr.length; ++i) {
    // Do something with `substr[i]`
}

ES5 für jeden:

substr.forEach(function(item) {
    // Do something with `item`
});

jQuery.each:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

Schauen Sie sich dies an, um detaillierte Informationen zu erhalten, oder überprüfen Sie MDN auf Schleifen durch ein Array in JavaScript und verwenden Sie jQuery. Überprüfen Sie jQuery für jedes Array .


27

Ich würde empfehlen, die Bibliothek underscore.js zu verwenden. Es bietet Ihnen verschiedene Funktionen, mit denen Sie Arrays / Sammlungen durchlaufen können.

Zum Beispiel:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

7
Für neue Entdecker dieser Frage möchte ich nur auf Lo-Dash hinweisen , einen spirituellen Nachfolger von Underscore, der sie in vielerlei Hinsicht verbessert.
Mark Reed

3
Warum verwenden, underscorewenn ECMA-262 das forEachMethor hinzugefügt wurde . Der native Code ist immer besser.
Walter Chapilliquen - wZVanG

27

Array-Schleife:

for(var i = 0; i < things.length; i++){
    var thing = things[i];
    console.log(thing);
}

Objektschleife:

for(var prop in obj){
    var propValue = obj[prop];
    console.log(propValue);
}

27

Ja , Sie können dasselbe in JavaScript mithilfe einer Schleife tun, aber nicht darauf beschränkt . Es gibt viele Möglichkeiten, eine Schleife über Arrays in JavaScript durchzuführen. Stellen Sie sich vor, Sie haben dieses Array unten und möchten eine Schleife darüber erstellen:

var arr = [1, 2, 3, 4, 5];

Dies sind die Lösungen:

1) Für Schleife

Eine forSchleife ist eine übliche Methode zum Durchlaufen von Arrays in JavaScript, wird jedoch nicht als die schnellste Lösung für große Arrays angesehen:

for (var i=0, l=arr.length; i<l; i++) {
  console.log(arr[i]);
}

2) While-Schleife

Eine while-Schleife wird als der schnellste Weg zum Durchlaufen langer Arrays angesehen, wird jedoch im JavaScript-Code normalerweise weniger verwendet:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3) Tun Sie, während
A do whiledasselbe tut wie whilemit einem Syntaxunterschied wie unten:

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

Dies sind die Hauptmethoden zum Ausführen von JavaScript-Schleifen, aber es gibt noch einige weitere Möglichkeiten, dies zu tun.

Außerdem verwenden wir eine for inSchleife zum Schleifen von Objekten in JavaScript.

Auch Blick auf den map(), filter(), reduce()etc. Funktionen auf einem Array in JavaScript. Sie können Dinge viel schneller und besser machen als mit whileund for.

Dies ist ein guter Artikel, wenn Sie mehr über die asynchronen Funktionen über Arrays in JavaScript erfahren möchten.

Die funktionale Programmierung hat in der Entwicklungswelt heutzutage für Furore gesorgt. Und das aus gutem Grund: Mithilfe von Funktionstechniken können Sie deklarativeren Code schreiben, der auf einen Blick leichter zu verstehen ist, umgestaltet und getestet wird.

Einer der Eckpfeiler der funktionalen Programmierung ist die spezielle Verwendung von Listen und Listenoperationen. Und diese Dinge sind genau so, wie sie klingen: Anordnungen von Dingen und das, was Sie ihnen antun. Aber die funktionale Denkweise behandelt sie ein bisschen anders als Sie vielleicht erwarten.

In diesem Artikel wird genau untersucht, was ich als "große drei" Listenoperationen bezeichne: Zuordnen, Filtern und Reduzieren. Das Umhüllen dieser drei Funktionen ist ein wichtiger Schritt, um sauberen Funktionscode schreiben zu können, und öffnet die Türen zu den äußerst leistungsfähigen Techniken der funktionalen und reaktiven Programmierung.

Dies bedeutet auch, dass Sie nie wieder eine for-Schleife schreiben müssen.

Lesen Sie mehr >> hier :


Gibt es wirklich einen Leistungsunterschied vor einer for-Schleife und einer while-Schleife, wenn ein Array durchlaufen wird? Ich hatte den Eindruck, dass die Unterschiede hauptsächlich syntaktisch waren
Shea

24

Wenn sich jemand für die Leistungsseite der verschiedenen Mechanismen interessiert, die für Array-Iterationen verfügbar sind, habe ich die folgenden JSPerf-Tests vorbereitet:

https://jsperf.com/fastest-array-iterator

Leistungsergebnisse

Ergebnisse:

Der traditionelle for()Iterator ist bei weitem die schnellste Methode, insbesondere wenn er mit der zwischengespeicherten Array-Länge verwendet wird .

let arr = [1,2,3,4,5];

for(let i=0, size=arr.length; i<size; i++){
    // Do something
}

Die Array.prototype.forEach()und die Array.prototype.map()Methoden sind die langsamsten Näherungen, wahrscheinlich als Folge des Funktionsaufruf-Overheads .


ist besser zu verwenden i = i +1alsi++
DarckBlezzer

2
Könnte verbessert werden: Bitte verwenden Sie: ++ i anstelle von i ++, dies vermeidet ein temporäres Objekt. So werden Speicherplatz und CPU-Zeit reduziert (keine Zuordnung erforderlich)!
PowerStat

@PowerStat können Sie einen Link oder eine Referenz dazu bereitstellen? Ich habe noch nie davon gehört, klingt interessant ...
colxi

1
@colxi Für so interessante Dinge solltest du das Hardcore-C ++ - Zeug von Herb Sutter und Scott Meyers lesen. Das ++ i vs i ++ Ding stammt aus dem Buch: Außergewöhnliches C ++: 47 Engineering-Rätsel, Programmierprobleme und Lösungen - ich denke , Sie können es auch auf gotw.ca finden, aber es kann für jede Programmiersprache bewiesen werden.
PowerStat

21

Wenn Sie die jQuery-Bibliothek verwenden, sollten Sie http://api.jquery.com/jQuery.each/ verwenden.

Aus der Dokumentation:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

Rückgabe: Objekt

Beschreibung: Eine generische Iteratorfunktion, mit der Objekte und Arrays nahtlos durchlaufen werden können. Arrays und Array-ähnliche Objekte mit einer Längeneigenschaft (z. B. das Argumentobjekt einer Funktion) werden durch einen numerischen Index von 0 bis Länge 1 iteriert. Andere Objekte werden über ihre benannten Eigenschaften iteriert.

Die $.each()Funktion ist nicht dieselbe wie die $(selector).each(), mit der ausschließlich ein jQuery-Objekt durchlaufen wird. Die $.each() Funktion kann verwendet werden, um über jede Sammlung zu iterieren, unabhängig davon, ob es sich um eine Karte (JavaScript-Objekt) oder ein Array handelt. Im Fall eines Arrays wird dem Rückruf jedes Mal ein Array-Index und ein entsprechender Array-Wert übergeben. (Auf den Wert kann auch über das thisSchlüsselwort zugegriffen werden , aber Javascript umschließt den thisWert immer als Objecteinen einfachen Wert, selbst wenn es sich um einen einfachen Zeichenfolgen- oder Zahlenwert handelt.) Die Methode gibt ihr erstes Argument zurück, das Objekt, das iteriert wurde.


9
jQuery für alles?
Ausnahme

6
Mit Ausnahme einverstanden. Unterschätzen Sie nicht die Auswirkungen zusätzlicher Abhängigkeiten. Ich würde davon abraten, außer in Code, der ohnehin schon stark jQuery verwendet.
Stijn de Witt

2
Update: Heutzutage können Sie Array.forEach verwenden , um mit nativen Arrays den gleichen Effekt zu erzielen.
Stijn de Witt

20

Ich habe diese Variante noch nicht gesehen, die mir persönlich am besten gefällt:

Gegeben ein Array:

var someArray = ["some", "example", "array"];

Sie können eine Schleife durchlaufen, ohne jemals auf die Eigenschaft length zuzugreifen:

for (var i=0, item; item=someArray[i]; i++) {
  // item is "some", then "example", then "array"
  // i is the index of item in the array
  alert("someArray[" + i + "]: " + item);
}

Sehen Sie sich diese JsFiddle an, die Folgendes demonstriert: http://jsfiddle.net/prvzk/

Dies funktioniert nur für Arrays, die dies nicht sind dünn sind. Dies bedeutet, dass an jedem Index im Array tatsächlich ein Wert vorhanden ist. In der Praxis habe ich jedoch festgestellt, dass ich in JavaScript kaum spärliche Arrays verwende ... In solchen Fällen ist es normalerweise viel einfacher, ein Objekt als Map / Hashtable zu verwenden. Wenn Sie ein Array mit geringer Dichte haben und eine Schleife über 0 .. length-1 durchführen möchten, benötigen Sie das Konstrukt for (var i = 0; i <someArray.length; ++ i), aber Sie benötigen weiterhin einif innerhalb der Schleife um zu überprüfen, ob das Element am aktuellen Index tatsächlich definiert ist.

Wie CMS in einem Kommentar unten erwähnt, können Sie dies auch nur für Arrays verwenden, die keine falschen Werte enthalten. Das Array von Zeichenfolgen aus dem Beispiel funktioniert, aber wenn Sie leere Zeichenfolgen oder Zahlen mit 0 oder NaN usw. haben, wird die Schleife vorzeitig abgebrochen. Auch in der Praxis ist dies für mich kaum ein Problem, aber es ist etwas zu beachten, was dies zu einer Schleife macht, über die man nachdenken muss, bevor man es benutzt ... Das kann es für einige Leute disqualifizieren :)

Was ich an dieser Schleife mag, ist:

  • Es ist kurz zu schreiben
  • Sie müssen nicht auf die Eigenschaft length zugreifen (geschweige denn zwischenspeichern)
  • Das Element, auf das zugegriffen werden soll, wird automatisch im Schleifenkörper unter dem von Ihnen ausgewählten Namen definiert.
  • Kombiniert sehr natürlich mit array.push und array.splice, um Arrays wie Listen / Stapel zu verwenden

Der Grund dafür ist, dass die Array-Spezifikation vorschreibt, dass beim Lesen eines Elements aus einem Index> = der Länge des Arrays undefiniert zurückgegeben wird. Wenn Sie an einen solchen Ort schreiben, wird die Länge tatsächlich aktualisiert.

Für mich emuliert dieses Konstrukt am ehesten die Java 5-Syntax, die ich liebe:

for (String item : someArray) {
}

... mit dem zusätzlichen Vorteil, dass Sie auch den aktuellen Index innerhalb der Schleife kennen


13
Beachten Sie, dass mit diesem Ansatz der Schleife so bald aufhören wird es findet einen Falsey Wert , wie eine leere Zeichenfolge, 0, false, NaN, nulloder undefined, noch bevor ierreicht die Länge, zum Beispiel: jsfiddle.net/prvzk/1
CMS

3
Die Schleifenbedingung könnte sein (item=someArray[i]) !== undefined.
Daniel1426

18

Es gibt eine Methode, um nur eigene Objekteigenschaften zu durchlaufen, ohne die des Prototyps:

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

Es werden jedoch weiterhin benutzerdefinierte Eigenschaften durchlaufen.

In JavaScript kann jedem Objekt eine benutzerdefinierte Eigenschaft zugewiesen werden, einschließlich eines Arrays.

Wenn man über sparsed Array iterieren möchte for (var i = 0; i < array.length; i++) if (i in array)oder array.forEachmit verwendet es5shimwerden soll.


Und wie wäre es mit for (var i in array) if (++i)?
Daniel Sokolowski

15

Es gibt verschiedene Möglichkeiten, dies in JavaScript zu tun. Die ersten beiden Beispiele sind JavaScript-Beispiele. Die dritte verwendet eine JavaScript-Bibliothek, dh jQuery nutzt die .each()Funktion.

var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>


for...insollte für Array-ähnliche Objekte vermieden werden
brk

15

Der eleganteste und schnellste Weg

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


Bearbeitet (weil ich mich geirrt habe)


Vergleichen Sie die Methoden zum Durchlaufen eines Arrays von 100000 Elementen und führen Sie jedes Mal eine minimale Operation mit dem neuen Wert aus.

Vorbereitung:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };

        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

Tests:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>

Diese Schleife scheint nicht der Reihenfolge der Elemente im Array zu folgen.
Deniz Ozger

Mein Test war falsch. Es ist richtig und zeigt jetzt alle LOOPS. jsperf.com/native-loop-performance/16
Molokoloco

@bergi ist richtig. Diese Schleife löscht das Array, während es es durchläuft. In den meisten Fällen nicht das, was Sie wollen.
Stijn de Witt

4
bricht auf falsey Gegenständen.
NJZK2

12

Der optimierte Ansatz besteht darin, die Länge des Arrays zwischenzuspeichern und ein einzelnes var-Muster zu verwenden, das alle Variablen mit einem einzelnen var-Schlüsselwort initialisiert.

var i, max, myStringArray = ["Hello","World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
    alert(myStringArray[i]);
   //Do something
}

Wenn die Reihenfolge der Iteration keine Rolle spielt, sollten Sie die umgekehrte Schleife ausprobieren. Sie ist am schnellsten, da sie das Testen von Overhead-Bedingungen und das Dekrementieren in einer Anweisung reduziert:

var i,myStringArray = ["item1","item2"];
for (i =  myStringArray.length; i--) {
    alert(myStringArray[i]);
}

oder besser und sauberer während der Schleife zu verwenden:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}

12

In JavaScript gibt es so viele Lösungen, um ein Array zu schleifen.

Der folgende Code ist beliebt

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

for (let i = 0; i < items.length; i++) {
  console.log(items[i])
}

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()


12

Wenn Sie jQuery verwenden möchten, enthält die Dokumentation ein schönes Beispiel:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

12

Meiner Meinung nach ist es am besten, die Funktion Array.forEach zu verwenden. Wenn Sie das nicht verwenden können, würde ich vorschlagen, die Polyfüllung von MDN zu erhalten. Um es verfügbar zu machen, ist es sicherlich die sicherste Möglichkeit, ein Array in JavaScript zu durchlaufen.

Array.prototype.forEach ()

Wie andere vorgeschlagen haben, ist dies fast immer das, was Sie wollen:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

Dadurch wird sichergestellt, dass alles, was Sie für die Verarbeitung des Arrays benötigen, innerhalb dieses Bereichs bleibt und dass Sie nur die Werte des Arrays verarbeiten, nicht die Objekteigenschaften und andere Elemente for .. Elemente.

Verwendung eines normalen C-Stils for Schleife funktioniert in den meisten Fällen. Es ist nur wichtig zu bedenken, dass alles in der Schleife seinen Bereich mit dem Rest Ihres Programms teilt. Das {} erstellt keinen neuen Bereich.

Daher:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

for(var i = 0; i<numbers.length; ++i){
  sum += numbers[i];
}

alert(i);

gibt "11" aus - was möglicherweise das ist, was Sie wollen oder nicht.

Ein funktionierendes jsFiddle-Beispiel: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/


10

Es ist nicht 100% identisch, aber ähnlich:

   var myStringArray = ['Hello', 'World']; // array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }


1
Es scheint, dass dies auf ähnliche Probleme stoßen würde wie andere bei der Verwendung mit einem Array-Objekt, da Prototyp-Mitgliedsvariablen auch vom for in erfasst würden.
Kzqai

9

Zum Beispiel habe ich in einer Firefox-Konsole verwendet:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})

9
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

Viel sauberer ...


Das ist nicht sehr sauber im Vergleich zu z.forEach(j => console.log(j));.
Sapphire_Brick

9

Kurze Antwort: ja. Sie können damit machen:

var myArray = ["element1", "element2", "element3", "element4"];

for (i = 0; i < myArray.length; i++) {
  console.log(myArray[i]);
}

In einer Browserkonsole wird etwas wie "Element1", "Element2" usw. gedruckt angezeigt.


9

Sie können entweder verwenden Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach((item, index)=>{
   //Some code...
});

Oder Array.prototype.map(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.map((item, index)=>{
   //Some code...
});

Oder die zuvor erwähnte jquery oder for loop-Wege.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.