Jede Programmiersprache hat Schleifen. Schleifen führen eine Operation (d. h. eine Arbeitsaufgabe) mehrmals aus, normalerweise einmal für jedes Element in einem Array oder einer Liste oder einfach, um eine Operation zu wiederholen, bis eine bestimmte Bedingung erfüllt ist.
Insbesondere JavaScript hat ziemlich viele verschiedene Arten von Schleifen. Ich habe nicht einmal alle davon benutzt, also habe ich zu meiner eigenen Neugier gedacht, ich würde einen groben Überblick über sie geben. Und wie sich herausstellt, gibt es ziemlich gute Gründe, warum ich zumindest ein paar der verschiedenen Arten noch nicht benutzt habe.
Lassen Sie uns also for jetzt eine while lang damit verbringen, die verschiedenen Arten von Schleifen zu erkunden, was wir mit each von ihnen tun können und warum Sie eine gegenüber einer anderen verwenden könnten. (Sie werden denken, dass dieses kleine Wortspiel am Ende absolut urkomisch ist.)
Die while- und do...while-Schleifen
Zuerst kommt die while-Schleife. Sie ist die grundlegendste Art von Schleife und hat das Potenzial, in vielen Fällen am einfachsten zu lesen und am schnellsten zu sein. Sie wird normalerweise verwendet, um etwas zu tun, bis eine bestimmte Bedingung erfüllt ist. Sie ist auch der einfachste Weg, eine Endlosschleife oder eine Schleife zu erstellen, die niemals stoppt. Es gibt auch die do...while-Anweisung. Eigentlich ist der einzige Unterschied, dass die Bedingung am Ende anstatt am Anfang jeder Iteration geprüft wird.
// remove the first item from an array and log it until the array is empty
let queue1 = ["a", "b", "c"];
while (queue1.length) {
let item = queue1.shift();
console.log(item);
}
// same as above but also log when the array is empty
let queue2 = [];
do {
let item = queue2.shift() ?? "empty";
console.log(item);
} while (queue2.length);
Die for-Schleife
Als nächstes kommt die for-Schleife. Sie sollte die bevorzugte Methode sein, um etwas eine bestimmte Anzahl von Malen auszuführen. Wenn Sie eine Operation wiederholen müssen, sagen wir, 10 Mal, dann verwenden Sie stattdessen eine for-Schleife. Diese spezielle Schleife kann für Programmieranfänger einschüchternd sein, aber das Umschreiben derselben Schleife in einer while-ähnlichen Schleife kann helfen, die Syntax zu veranschaulichen und sie leichter im Gedächtnis zu behalten.
// log the numbers 1 to 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// same thing but as a while loop
let i = 1; // the first part of a for loop
// the second
while (i <= 5) {
console.log(i);
i++; // the third
}
("end");
Die for...of- und for await...of-Schleifen
Eine for...of-Schleife ist der einfachste Weg, ein Array zu durchlaufen.
let myList = ["a", "b", "c"];
for (let item of myList) {
console.log(item);
}
Sie sind jedoch nicht auf Arrays beschränkt. Technisch können sie alles durchlaufen, was das sogenannte Iterable-Protokoll implementiert. Es gibt einige integrierte Typen, die das Protokoll implementieren: Arrays, Maps, Sets und Strings, um die gebräuchlichsten zu nennen, aber Sie können das Protokoll auch in Ihrem eigenen Code implementieren. Dazu fügen Sie einer beliebigen Objekts eine [Symbol.iterator]-Methode hinzu, und diese Methode sollte einen Iterator zurückgeben. Es ist etwas verwirrend, aber die Essenz ist, dass Iterables Dinge sind, die eine spezielle Methode haben, die Iteratoren zurückgibt; eine Fabrikmethode für Iteratoren, wenn Sie so wollen. Ein spezieller Funktionstyp namens Generator ist eine Funktion, die sowohl ein Iterable als auch einen Iterator zurückgibt.
let myList = {
*[Symbol.iterator]() {
yield "a";
yield "b";
yield "c";
},
};
for (let item of myList) {
console.log(item);
}
Es gibt die async-Version all der Dinge, die ich gerade erwähnt habe: async-Iterables, async-Iteratoren und async-Generatoren. Sie würden ein async-Iterable mit for await...of verwenden.
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
// this time we're not making an iterable, but a generator
async function* aNumberAMinute() {
let i = 0;
while (true) {
// an infinite loop
yield i++;
// pause a minute
await delay(60_000);
}
}
// it's a generator, so we need to call it ourselves
for await (let i of aNumberAMinute()) {
console.log(i);
// stop after one hour
if (i >= 59) {
break;
}
}
Eine nicht offensichtliche Sache an der await...of-Anweisung ist, dass Sie sie mit nicht-asynchronen Iterables verwenden können und sie wird problemlos funktionieren. Das Gegenteil ist jedoch nicht der Fall; Sie können keine async-Iterables mit der for...of-Anweisung verwenden.
Die forEach- und map-Schleifen
Obwohl dies technisch gesehen keine Schleifen im eigentlichen Sinne sind, können Sie sie verwenden, um eine Liste zu durchlaufen.
Hier ist die Sache mit der forEach-Methode. Historisch gesehen war sie viel langsamer als die Verwendung einer for-Schleife. Ich denke, in einigen Fällen stimmt das vielleicht nicht mehr, aber wenn die Leistung eine Rolle spielt, würde ich sie vermeiden. Und jetzt, wo wir for...of haben, bin ich mir nicht sicher, ob es noch viel Grund gibt, sie zu verwenden. Ich schätze, der einzige Grund, warum sie immer noch vorkommen könnte, ist, wenn Sie eine Funktion als Callback bereit haben, aber Sie könnten dieselbe Funktion auch einfach aus dem Körper von for...of aufrufen.
forEach empfängt jedoch auch den Index für jedes Element, sodass dies etwas sein könnte, das Sie auch benötigen. Letztendlich wird die Entscheidung zur Verwendung wahrscheinlich davon abhängen, ob anderer Code, mit dem Sie arbeiten, ihn verwendet, aber ich persönlich würde die Verwendung vermeiden, wenn ich etwas Neues schreibe.
let myList = ["a", "b", "c"];
for (let item of myList) {
console.log(item);
}
// but maybe if I need the index use forEach
["a", "b", "c"].forEach((item, index) => {
console.log(`${index}: ${item}`);
});
In der Zwischenzeit konvertiert map im Wesentlichen ein Array in ein anderes. Es hat immer noch die gleichen Leistungsauswirkungen wie forEach, aber es ist etwas besser lesbar als die Alternative. Es ist jedoch sicherlich subjektiv, und genau wie bei forEach möchten Sie das tun, was der Rest Ihres anderen Codes tut. Sie sehen es sehr oft in React und React-inspirierten Bibliotheken als primäre Methode, um durch ein Array zu iterieren und eine Liste von Elementen innerhalb von JSX auszugeben.
function MyList({items}) {
return (
<ul>
{items.map((item) => {
return <li>{item}</li>;
})}
</ul>
);
}
Die for...in-Schleife
Diese Liste von Schleifen in JavaScript wäre nicht vollständig, ohne die for...in-Anweisung zu erwähnen, da sie durch die Felder eines Objekts iterieren kann. Sie besucht jedoch auch Felder, die über die Prototypenkette des Objekts geerbt wurden, und ich habe sie aus diesem Grund ehrlich gesagt immer vermieden.
Das gesagt, wenn Sie ein Objektliteral haben, dann könnte for...in eine praktikable Methode sein, um durch die Schlüssel dieses Objekts zu iterieren. Außerdem ist es erwähnenswert, dass, wenn Sie schon lange JavaScript programmieren, Sie sich vielleicht erinnern, dass die Reihenfolge der Schlüssel früher zwischen den Browsern inkonsistent war, aber jetzt ist die Reihenfolge konsistent. Jeder Schlüssel, der ein Array-Index sein könnte (d. h. positive ganze Zahlen), steht zuerst in aufsteigender Reihenfolge, und dann alles andere in der Reihenfolge, wie es geschrieben wurde.
let myObject = {
a: 1,
b: 2,
c: 3,
};
for (let k in myObject) {
console.log(myObject[k]);
}
Zusammenfassung
Schleifen sind etwas, das viele Programmierer täglich verwenden, obwohl wir sie vielleicht für selbstverständlich halten und nicht zu viel darüber nachdenken.
Aber wenn Sie einen Schritt zurücktreten und sich alle Wege ansehen, die wir in JavaScript haben, um durch Dinge zu iterieren, stellt sich heraus, dass es mehrere Möglichkeiten gibt, dies zu tun. Nicht nur das, sondern es gibt signifikante – wenn auch nuancierte – Unterschiede zwischen ihnen, die Ihre Herangehensweise an Skripte beeinflussen können und werden.