Tutorials › Teil 1: Grundlagen

Kapitel 5 von 16

Etwas wiederholen

Das Einmaleins der Sieben, von Hand:

zeige("7 x 1 = 7");
zeige("7 x 2 = 14");
zeige("7 x 3 = 21");

Und so weiter bis zehn. Niemand schreibt das so.

for (let i = 1; i <= 10; i++) {
  zeige(`7 x ${i} = ${7 * i}`);
}

Die drei Teile im Kopf der for-Schleife

Zwischen den Klammern stehen drei Anweisungen, getrennt durch Semikolons.

let i = 1 läuft einmal, ganz am Anfang. Hier entsteht der Zähler.

i <= 10 wird vor jedem Durchgang geprüft. Solange die Bedingung wahr ist, geht es weiter. Wird sie falsch, ist Schluss.

i++ läuft nach jedem Durchgang. Es ist die Kurzform für i = i + 1.

Der Name i ist reine Gewohnheit, kommt von Index und ist seit den Sechzigern in Gebrauch. Bei verschachtelten Schleifen nimmt man j und k. Wenn ein aussagekräftigerer Name passt, nimm den.

Rückwärts geht genauso:

for (let i = 5; i > 0; i--) {
  zeige(i);
}
zeige("Start!");

for...of für Listen

Sobald du eine Liste durchgehst, brauchst du den Zähler meistens gar nicht. Dann ist diese Form die klarere:

const anbieter = ["Telekom", "Vodafone", "o2", "PYUR"];

for (const name of anbieter) {
  zeige(name);
}

Kein Index, keine Abbruchbedingung, kein Hochzählen. Es kann nichts danebengehen.

Brauchst du doch die Position, liefert entries() beides:

const anbieter = ["Telekom", "Vodafone", "o2"];

for (const [platz, name] of anbieter.entries()) {
  zeige(`${platz + 1}. ${name}`);
}

for...of funktioniert nicht nur mit Arrays, sondern mit allem, was sich der Reihe nach durchlaufen lässt. Text zum Beispiel:

for (const zeichen of "Morse") {
  zeige(zeichen);
}

while

for passt, wenn du vorher weißt, wie oft. while passt, wenn du es nicht weißt.

let rest = 1000;
let halbierungen = 0;

while (rest > 1) {
  rest = rest / 2;
  halbierungen++;
}

zeige("Nach", halbierungen, "Halbierungen unter 1.");

Es gibt eine Variante, die den Rumpf mindestens einmal ausführt und erst danach prüft:

let wurf;
let versuche = 0;

do {
  wurf = Math.floor(Math.random() * 6) + 1;
  versuche++;
} while (wurf !== 6);

zeige("Nach", versuche, "Würfen eine Sechs.");

Lad die Seite ein paar Mal neu, die Zahl schwankt. do...while sieht man selten, aber für „mindestens einmal, dann so lange bis" ist es genau richtig.

Abbrechen und überspringen

break verlässt die Schleife sofort. continue überspringt nur den Rest des aktuellen Durchgangs.

const zahlen = [4, 9, 12, 7, 20, 3];

for (const z of zahlen) {
  if (z % 2 !== 0) continue;
  if (z > 15) break;
  zeige("gerade und klein genug:", z);
}

Der Prozentoperator liefert den Rest einer Division. z % 2 ist null bei geraden Zahlen. Das ist die übliche Art, auf gerade oder ungerade zu prüfen.

Die var-Falle

Hier ist der Grund, warum Kapitel 3 so bestimmt gegen var argumentiert hat.

for (var i = 1; i <= 3; i++) {
  setTimeout(function () { zeige("mit var:", i); }, 10);
}

for (let j = 1; j <= 3; j++) {
  setTimeout(function () { zeige("mit let:", j); }, 20);
}

Die erste Schleife gibt dreimal die Vier aus. Die zweite gibt Eins, Zwei, Drei aus.

Der Grund: var i existiert genau einmal für die ganze Funktion. Wenn die verzögerten Aufrufe nach zehn Millisekunden endlich drankommen, ist die Schleife längst durch und i steht auf vier. Alle drei schauen auf dieselbe Schublade.

let j legt für jeden Durchgang eine eigene Schublade an. Jeder Aufruf hat seinen eigenen Wert.

Dieses Verhalten hat in den Zweitausendern unzählige Stunden Fehlersuche gekostet. Es gab Umgehungen, sie waren umständlich, und heute braucht man sie nicht mehr.

Verschachteln

Zwei Schleifen ineinander ergeben eine Fläche. Das kleine Einmaleins komplett:

for (let reihe = 1; reihe <= 5; reihe++) {
  let zeile = "";
  for (let spalte = 1; spalte <= 5; spalte++) {
    zeile += String(reihe * spalte).padStart(4);
  }
  zeige(zeile);
}

Die innere Schleife läuft für jeden einzelnen Durchgang der äußeren komplett durch. Bei fünf mal fünf sind das fünfundzwanzig Durchgänge.

Das skaliert schlecht. Zwei verschachtelte Schleifen über tausend Einträge sind eine Million Durchgänge. Wenn dir so etwas unterkommt und es langsam wird, ist das meistens die Stelle.

Schleifen und Bedingungen sind die Bausteine. Was fehlt, ist eine Art, Bausteine zu benennen und wiederzuverwenden.