Tutorials › Teil 1: Grundlagen
Kapitel 4 von 16
Entscheidungen treffen
const alter = 17;
if (alter >= 18) {
zeige("Volljährig.");
} else {
zeige("Noch nicht.");
}
Ändere die 17 in eine 18, und die Ausgabe kippt. Mehr ist an if erst mal nicht dran.
Interessant wird es bei der Bedingung in den Klammern, und da lauern die Fallen.
Drei Gleichheitszeichen, nicht zwei
JavaScript hat zwei Vergleichsoperatoren, und einer davon ist kaputt.
zeige("mit zwei:", 5 == "5");
zeige("mit drei:", 5 === "5");
zeige("noch schlimmer:", 0 == "");
zeige("und das:", null == undefined);
== versucht, beide Seiten auf einen gemeinsamen Typ zu bringen, bevor es vergleicht. Die Regeln dafür füllen mehrere Seiten Spezifikation und niemand hat sie im Kopf.
=== vergleicht ohne Umwandlung. Verschiedener Typ heißt verschieden, fertig.
Nimm ===. Immer. Das Gegenstück zu != heißt !==.
Eine einzige Ausnahme kennen erfahrene Leute: x == null ist wahr für null und für undefined und ist eine kompakte Art, beides auf einmal abzufangen. Wenn dich das irritiert, schreib x === null || x === undefined und gut.
Mehrere Fälle
const punkte = 73;
let note;
if (punkte >= 90) {
note = "sehr gut";
} else if (punkte >= 75) {
note = "gut";
} else if (punkte >= 60) {
note = "befriedigend";
} else {
note = "durchgefallen";
}
zeige(punkte, "Punkte:", note);
Die Reihenfolge ist hier alles. Der Browser prüft von oben nach unten und steigt beim ersten Treffer aus. Stünde punkte >= 60 ganz oben, bekämen auch 95 Punkte ein „befriedigend".
switch, wenn es um einen einzigen Wert geht
Wenn du immer dieselbe Variable gegen feste Werte prüfst, wird die if-Kette schnell zäh.
const taste = "ArrowLeft";
switch (taste) {
case "ArrowLeft":
zeige("nach links");
break;
case "ArrowRight":
zeige("nach rechts");
break;
case "Escape":
case "Backspace":
zeige("abbrechen");
break;
default:
zeige("unbekannt:", taste);
}
Das break ist keine Verzierung. Ohne es läuft die Ausführung in den nächsten Fall weiter, und zwar ohne dessen Bedingung zu prüfen. Genau das nutzt der Block mit "Escape" und "Backspace" aus: Zwei Werte, eine Reaktion.
Vergessenes break ist eine der häufigsten Ursachen für merkwürdiges Verhalten in fremdem Code. switch vergleicht übrigens mit ===, insofern gibt es dort die Typfalle nicht.
Und, oder, nicht
const angemeldet = true;
const guthaben = 0;
zeige(angemeldet && guthaben > 0);
zeige(angemeldet || guthaben > 0);
zeige(!angemeldet);
Soweit erwartbar. Weniger erwartbar ist, was diese Operatoren zurückgeben, wenn man keine Wahrheitswerte hineinsteckt.
zeige("A:", "" || "Ersatzwert");
zeige("B:", "Vorhanden" || "Ersatzwert");
zeige("C:", 0 || "Ersatzwert");
zeige("D:", null && "wird nie erreicht");
|| liefert die linke Seite, wenn die als wahr gilt, sonst die rechte. Es gibt keinen Wahrheitswert zurück, sondern einen der beiden Werte selbst. Das ist praktisch für Vorgabewerte.
Zeile C zeigt das Problem daran. Die Null ist ein gültiger Wert, aber sie gilt als falsch, und deshalb wird sie durch den Ersatzwert überschrieben. Bei einem Zähler, einem Preis oder einer Menge ist das ein Fehler.
Dafür gibt es ??:
const menge = 0;
zeige("mit ||:", menge || 10);
zeige("mit ??:", menge ?? 10);
zeige("bei undefined:", undefined ?? 10);
?? springt nur bei null und undefined ein. Für Vorgabewerte ist das fast immer das, was du willst.
Das Fragezeichen
Für kurze Entscheidungen, deren Ergebnis in eine Variable soll, ist eine vierzeilige if-Konstruktion viel Aufwand.
const anzahl = 1;
const text = anzahl === 1 ? "ein Treffer" : anzahl + " Treffer";
zeige(text);
Bedingung, Fragezeichen, Wert für wahr, Doppelpunkt, Wert für falsch.
Gut lesbar, solange es bei einer Ebene bleibt. Verschachtelte Fragezeichen-Operatoren sind eine Zumutung für jeden, der den Code später lesen muss, dich selbst eingeschlossen.
Früh aussteigen
Eine Angewohnheit, die Code deutlich lesbarer macht: Sonderfälle sofort abhandeln und dann verschwinden, statt den Normalfall in immer tiefere Klammern zu schachteln.
Schwer lesbar:
function preis(artikel) {
if (artikel) {
if (artikel.verfuegbar) {
if (artikel.preis > 0) {
return artikel.preis;
} else {
return "kostenlos";
}
} else {
return "nicht lieferbar";
}
} else {
return "unbekannt";
}
}
Dasselbe, flach:
function preis(artikel) {
if (!artikel) return "unbekannt";
if (!artikel.verfuegbar) return "nicht lieferbar";
if (artikel.preis === 0) return "kostenlos";
return artikel.preis;
}
zeige(preis(null));
zeige(preis({ verfuegbar: false }));
zeige(preis({ verfuegbar: true, preis: 0 }));
zeige(preis({ verfuegbar: true, preis: 12.5 }));
Neun Zeilen statt achtzehn, und man liest sie von oben nach unten wie eine Liste von Bedingungen. Was function und return genau tun, kommt in Kapitel 6.
Als Nächstes: Dinge mehrfach tun, ohne sie mehrfach hinzuschreiben.