2.3 Verschiedene Zweige eines Programms
Ein Programm kann abhängig von bestimmten Bedingungen unterschiedliche Teile eines Programms durchlaufen. Man sagt auch: Es verzweigt sich. Verzweigungen gehören zu den wichtigen Kontrollstrukturen. In diesem Abschnitt lernen Sie unterschiedliche Arten von Bedingungen und Verzweigungen sowie ihre Auswirkungen kennen.
2.3.1 Verzweigungen mit »if … else«
Verzweigungen werden mithilfe der Anweisung if … else erzeugt. Nach dem if steht in runden Klammern eine Bedingung, die entweder erfüllt oder nicht erfüllt ist.
-
Falls die Bedingung erfüllt ist, wird die folgende Anweisung oder der folgende Block von Anweisungen ausgeführt. Einen Block von Anweisungen erkennen Sie an den geschweiften Klammern { … }.
-
Falls die Bedingung nicht erfüllt ist, wird, falls vorhanden, die Anweisung oder der Block von Anweisungen nach dem else ausgeführt.
Bedingungen werden mithilfe von Wahrheitswerten gebildet. Vergleichsoperatoren haben Wahrheitswerte als Ergebnis. Der Operator > steht für größer als; der Operator < steht für kleiner als; >= bedeutet größer als oder gleich; <= bedeutet kleiner als oder gleich. Mit == prüfen Sie hinsichtlich Gleichheit und mit != hinsichtlich Ungleichheit.
Beachten Sie besonders die doppelten Gleichheitszeichen bei dem Operator ==. Ein häufiger Fehler ist die Verwechslung mit dem Operator =, der zu einer Zuweisung und nicht zu einem Vergleich führt. Bei Zahlen können alle Vergleichsoperatoren eingesetzt werden, bei Zeichenketten nur die beiden letzten, == und !=.
Die Sonderform einer Verzweigung wird mithilfe des ternären Operators ?: erzeugt. Sie können damit einen Wert aufgrund einer Bedingung zuweisen.
Es folgt ein Beispiel mit insgesamt sechs Verzweigungen. Diese sind im Programm und in der Ausgabe zum besseren Verständnis nummeriert:
...
<body>
<script>
var a = 12, b = 7;
// 1: Einfache Verzweigung
if(a > b)
document.write("<p>1: a ist größer als b</p>");
// 2: Einfache Verzweigung, mit else
if(a < b)
document.write("<p>2: a ist kleiner als b</p>");
else
document.write("<p>2: a ist nicht kleiner als b</p>");
// 3: Einfache Verzweigung, mehrere Anweisungen im Block
if(a > b)
{
document.write("<p>3: a ist größer als b<br>");
document.write("3: Eine weitere Zeile</p>");
}
// 4: Mehrfache Verzweigung
if(a > b)
document.write("<p>4: a ist größer als b</p>");
else if(a < b)
document.write("<p>4: a ist kleiner als b</p>");
else
document.write("<p>4: a ist gleich b</p>");
// 5: Zeichenketten
var land = "Spanien";
if(land == "Spanien")
document.write("<p>5: Land ist Spanien</p>");
if(land != "Spanien")
document.write("<p>5: Land ist nicht Spanien</p>");
// 6: Ternärer Operator
var groesser = (a > b) ? a : b;
document.write("<p>6: Die größere Zahl ist " + groesser + "</p>");
</script>
</body></html>
In Verzweigung 1 wird die Bedingung a > b geprüft. Dies ergibt bei den hier genannten Zahlenwerten den Wahrheitswert true. Die Bedingung ist damit erfüllt. Daher wird die Methode document.write() aufgerufen. Falls a nicht größer als b ist, ergibt sich der Wahrheitswert false. Dann wird hier gar nichts ausgegeben, da es kein else gibt.
In Verzweigung 2 wird immer etwas ausgegeben, da es zu dem if auch ein else gibt.
In Verzweigung 3 wird ein Block von Anweisungen ausgeführt. Falls aufgrund einer Bedingung mehrere Anweisungen ausgeführt werden sollen, müssen diese immer in Blockklammern gesetzt werden. Falls die Klammern fehlen, wird nur die erste Anweisung abhängig von der Verzweigung ausgeführt. Die weiteren Anweisungen werden dann in jedem Fall ausgeführt, weil nicht mehr erkannt wird, dass sie ebenfalls zur Verzweigung gehören sollen.
In Verzweigung 4 werden alle Fälle der Reihe nach geprüft. Falls a nicht größer als b ist, wird geprüft, ob a kleiner als b ist. Falls dies auch nicht zutrifft, sind a und b gleich. Mit einer solchen Mehrfach-Verzweigung können Sie also auch drei oder mehr Fälle voneinander unterscheiden.
In Verzweigung 5 werden zwei Zeichenketten miteinander verglichen. Sie können Zeichenketten sinnvoll nur auf Gleichheit oder Ungleichheit hin prüfen.
In Teil 6 des Programms wird der ternäre Operator für die Zuweisung eines Wertes angewendet. Falls die Bedingung in den Klammern zutrifft, erhält die Variable den Wert nach dem ? (Fragezeichen), ansonsten den Wert nach dem : (Doppelpunkt).
In Abbildung 2.12 sehen Sie die Ausgabe des Programms.
Was wird ausgegeben, wenn Sie im Programm den Wert von b auf 17 setzen? Ermitteln Sie das Ergebnis zunächst durch Überlegung, ohne das geänderte Programm aufzurufen. Was geschieht bei b = 12?
Zwei Hinweise
-
Schreiben Sie übersichtliche, leicht lesbare Programme. Im Falle einer Verzweigung sollten Sie mit Einrückungen hinter if und else arbeiten, wie in obigem Programm.
-
Notieren Sie nach der Bedingung hinter einem if oder nach einem else kein Semikolon. Es sollte also nicht aussehen wie folgt: if(a > b); oder else;. Dies würde dazu führen, dass die Verzweigung unmittelbar endet und die folgenden Anweisungen immer ausgeführt würden. Es könnte auch passieren, dass gar keine Ausgabe erfolgt, weil das else ohne sein zugehöriges if erzeugt wird. Diese typischen Einsteigerfehler sind schwer zu finden.
2.3.2 Bestätigung anfordern
Die Methode confirm() des window-Objekts stellt im Zusammenhang mit einer Verzweigung eine weitere Möglichkeit zur Kommunikation mit dem Benutzer dar. Nach dem Aufruf der Methode erscheint ein Dialogfeld mit einer Frage sowie zwei Schaltflächen mit der Aufschrift OK bzw. Abbrechen. Ein Beispiel:
...
<body>
<script>
var antwort = confirm("Wollen Sie diese Aktion durchführen?");
if(antwort)
alert("Diese Aktion wird durchgeführt");
else
alert("Diese Aktion wird nicht durchgeführt");
</script>
</body></html>
Falls der Benutzer die Schaltfläche OK betätigt, wird true zurückgeliefert. Dies ist für die Verzweigung bereits ausreichend, da ein Wahrheitswert geliefert wird. Sie benötigen keinen Vergleichsoperator. Die Abfrage if(antwort == true) würde zum selben Ergebnis führen, ist aber unnötig lang. Nach Betätigung der Schaltfläche Abbrechen wird false geliefert. Dann wird der else-Zweig durchlaufen.
In Abbildung 2.13 sehen Sie das Dialogfeld mit der Frage.
2.3.3 Mehrere Bedingungen verknüpfen
Sollen mehrere Bedingungen miteinander verbunden werden, so können Sie die logischen Operatoren && für das logische Und bzw. || für das logische Oder nutzen. Beim logischen Und müssen alle einzelnen Bedingungen wahr sein, damit die gesamte Bedingung wahr ist. Beim logischen Oder reicht eine wahre Bedingung aus, damit die gesamte Bedingung wahr ist.
Außerdem gibt es den logischen Operator ! für das logische Nicht. Damit wird der Wahrheitswert einer Bedingung umgekehrt. Aus true wird false, und aus false wird true. Ein Beispiel:
...
<body>
<script>
var a = 12;
if(a >= 10 && a <= 20) // Und-Operator
document.write("<p>1: a liegt zwischen 10 und 20</p>");
if(a < 10 || a > 20) // Oder-Operator
document.write("<p>2: a liegt nicht zwischen 10 und 20</p>");
if(!(a < 10 || a > 20)) // Nicht-Operator
document.write("<p>3: a liegt zwischen 10 und 20</p>");
</script>
</body></html>
Im ersten Fall wird geprüft, ob die Zahl sowohl größer gleich 10 als auch kleiner gleich 20 ist, also ob sie im Zahlenbereich von 10 bis 20 liegt.
Der zweite Fall testet, ob die Zahl kleiner als 10 oder größer als 20 ist, also außerhalb des Zahlenbereichs liegt.
Mithilfe des Operators ! wird im dritten Fall festgestellt, ob die Zahl nicht außerhalb des Zahlenbereichs, also innerhalb des Zahlenbereichs liegt.
In Abbildung 2.14 sehen Sie die Ausgabe für den Zahlenwert 12.
Was wird ausgegeben, wenn Sie im Programm den Wert von a auf 25 setzen? Ermitteln Sie das Ergebnis zunächst durch Überlegung, ohne das Programm aufzurufen. Was ist bei a = –15?
Zwei Hinweise
-
Die Bedingung a>=10 || a<=20 wird von jeder Zahl erfüllt. Die Bedingung a<10 && a>20 wird von keiner Zahl erfüllt. Dies sind natürlich Verknüpfungen, die Sie vermeiden sollten.
-
Für die logischen Operatoren in JavaScript ist das sogenannte Short-Circuit-Verhalten definiert. Dies wird u. a. beim Einsatz von Funktionen wichtig. In Abschnitt 7.8.2 sehen Sie dazu ein anschauliches Beispiel.
2.3.4 Eingabe von Zahlen prüfen
In diesem Abschnitt wird eine vom Benutzer eingegebene Zahl mithilfe einer mehrfachen Verzweigung geprüft. Im Verlauf des Programms lernen Sie die folgenden nützlichen Funktionen und Methoden kennen:
-
Die Funktion isNaN() stellt fest, ob eine Variable keine gültige Zahl enthält.
-
Die Methode Math.random() erzeugt eine zufällige Zahl, die größer oder gleich 0 ist und kleiner als 1 ist.
-
Die Methode Math.abs() berechnet den Betrag einer Zahl, also die Zahl ohne ihr Vorzeichen. Aus dem Wert –5 wird +5, der Wert 5 bleibt +5.
-
random() und abs() sind Methoden des Math-Objekts, das Sie in Abschnitt 6.3 ausführlicher kennenlernen werden.
Das Beispielprogramm:
...
<body>
<script>
// Zufallswert und Eingabe
var zufall = Math.random();
var eingabe = prompt("Geben Sie eine Zahl von 0 bis 1 ein, ohne 1");
var zahl = parseFloat(eingabe);
// Auswertung
if(eingabe == null)
alert("Sie haben die Schaltfläche Abbrechen betätigt");
else if(eingabe == "")
alert("Sie haben nichts eingegeben");
else if(isNaN(eingabe))
alert("Sie haben keine gültige Zahl eingegeben");
else if(zahl < 0 || zahl >= 1)
alert("Sie haben keine Zahl im gültigen Bereich eingegeben");
else if(Math.abs(zufall - zahl) < 0.1)
alert("Sie sind nah dran");
else
alert("Sie sind weit weg");
// Kontrolle
alert("Zufall: " + zufall + "\nEingabe: " + eingabe
+ "\nisNaN(): " + isNaN(eingabe) + "\nZahl: " + zahl
+ "\nDifferenz: " + (zufall-zahl) + "\nBetrag: "
+ Math.abs(zufall-zahl));
</script>
</body></html>
Im ersten Teil des Programms wird eine Zufallszahl erzeugt und gespeichert. Mithilfe von prompt() gibt der Benutzer anschließend eine Zahl ein. Diese wird sowohl als Zeichenkette als auch als Zahl gespeichert.
Der zweite Teil des Programms enthält eine mehrfache Verzweigung. Falls die erste Bedingung nicht zutrifft, wird die zweite geprüft. Trifft diese auch nicht zu, wird die dritte geprüft usw.
Die Schaltfläche Abbrechen führt dazu, dass der Wert null gespeichert wird. Falls der Benutzer nichts eingibt und die Schaltfläche OK betätigt, so wird eine leere Zeichenkette gespeichert. Beides können Sie mithilfe des Operators == abfragen.
Der Name der Funktion isNaN() steht für is Not a Number. Die Methode liefert true, falls die Eingabe keine gültige Zahl enthält, ansonsten false. Die anschließende verknüpfte Bedingung prüft, ob die Zahl im gültigen Bereich liegt.
Nun wird die Differenz zwischen der Zufallszahl und der eingegebenen Zahl ermittelt. Von dieser Differenz wird der Betrag berechnet. Falls dieser Betrag kleiner als 0.1 ist, ist die Eingabe schon nahe dran.
Warum muss eigentlich der Betrag berechnet werden? Nehmen wir an, die Zufallszahl ist 0.34 und die Eingabe ist 0.3. Dann beträgt die Differenz 0.04, und Sie benötigen den Betrag nicht. Falls dagegen die Eingabe 0.5 ist, ist die Differenz –0.16, also kleiner als 0.1. Das wäre ohne die Berechnung des Betrags zwar nahe dran, aber sachlich falsch. Die Methode Math.abs() berechnet +0.16, und das ist nicht mehr nahe dran. So sollte es sein.
Als Letztes bietet das Programm eine Kontrollausgabe aller wichtigen Werte mithilfe von alert(). Diese Anweisung können Sie in Kommentarzeichen setzen, falls Sie die Ausgabe nicht sehen möchten.
Hinweis
Die Anweisung mit der Kontrollausgabe ist sehr lang und erstreckt sich aus Gründen der Übersichtlichkeit über mehrere Zeilen. Sie können innerhalb einer Anweisung an vielen Stellen einen Zeilenumbruch durchführen, allerdings nicht mitten in einem Schlüsselwort und nicht innerhalb einer Zeichenkette.
Abbildung 2.15 und Abbildung 2.16 zeigen mögliche Kontrollausgaben.
2.3.5 Wert und Typ von Variablen prüfen
Die Operatoren === und !== prüfen noch etwas genauer als die Operatoren == und !=. Bei einer Bedingung mit === müssen sowohl der Wert der Variablen als auch der Typ dieses Werts übereinstimmen. Es wird also auch getestet, ob es sich bei dem Wert um eine Zahl, eine Zeichenkette oder einen Wahrheitswert handelt.
In diesem Zusammenhang ist auch der Operator typeof interessant. Er liefert Ihnen den Typ des Werts einer Variablen. Es folgt ein Programm mit den genannten Operatoren:
...
<body>
<script>
var a = 4711;
var b = "4711";
var c = 4711;
var d = true;
document.write("<p>a: " + a + ", " + typeof a + "<br>");
document.write("b: " + b + ", " + typeof b + "<br>");
document.write("c: " + c + ", " + typeof c + "<br>");
document.write("d: " + d + ", " + typeof d + "</p>");
if(a == b)
document.write("a == b<br>");
if(a !== b)
document.write("a !== b<br>");
if(a === c)
document.write("a === c");
</script>
</body></html>
In Abbildung 2.17 sehen Sie jeweils den Namen, den Wert und (dank typeof) den Typ des Werts der vier Variablen, die im Programm genutzt werden. Im Falle einer Zahl liefert typeof die Bezeichnung number, im Falle einer Zeichenkette string und im Falle eines Wahrheitswerts boolean.
Die Variablen a und b enthalten beide den Wert 4711, allerdings einmal als Zahl, einmal als Zeichenkette. Aufgrund der Wertgleichheit liefert der Vergleich mithilfe des Operators == den Wert true. Da aber die Typen nicht übereinstimmen, liefert der Vergleich mithilfe des Operators !== ebenfalls true.
Im Falle von a und c ist es anders. Beides sind Zahlen mit dem Wert 4711, daher liefert der Vergleich mithilfe des Operators === den Wert true.
2.3.6 Priorität der Operatoren
Die Operatoren haben in JavaScript unterschiedliche Prioritäten. Falls bei einer Anweisung mehrere Operatoren zum Einsatz kommen, werden zunächst die Teile der Anweisung ausgeführt, die die höhere Priorität haben. Bei gleicher Priorität werden die Anweisungsteile von links nach rechts ausgeführt.
Tabelle 2.1 zeigt die Prioritäten der bisher genutzten Operatoren. Sie beginnt mit den Operatoren, die die höchste Priorität haben.
Operatoren | Erläuterung |
---|---|
( ) | Klammern |
! – ++ -- | logisches Nicht, negatives Vorzeichen, Inkrement, Dekrement |
** | Potenzierung |
* / % | Multiplikation, Division, Modulo |
+ - | Addition, Subtraktion |
<<= >>= | kleiner, kleiner gleich, größer, größer gleich |
== != === !== | gleich, ungleich, mit und ohne Typvergleich |
&& | logisches Und |
|| | logisches Oder |
= += -= | Zuweisungen |
2.3.7 Verzweigungen mit »switch … case«
In JavaScript können Sie Verzweigungen mithilfe von if … else, aber auch mithilfe von switch … case notieren. Es ergeben sich zwar daraus keine zusätzlichen Möglichkeiten, denn jede switch … case-Verzweigung kann durch eine if … else-Verzweigung ersetzt werden. Allerdings kann ein solcher Ersatz durch if … else sehr umständlich sein. Im Sinne eines übersichtlichen, leicht lesbaren Programms ist switch … case daher bei bestimmten Verzweigungen zu empfehlen. Ein Beispiel:
...
<body>
<script>
var land = prompt("Bitte ein Land eingeben:");
switch(land)
{
case "Italien":
alert("Hauptstadt des Staates: Rom");
break;
case "England":
case "Wales":
case "Schottland":
alert("Hauptstadt des Staates: London");
break;
default:
alert("Hauptstadt des Staates nicht bekannt");
}
</script>
</body></html>
Der Benutzer soll den Namen eines Landes eingeben. Anschließend wird die eingegebene Zeichenkette mithilfe von switch … case untersucht. Nach switch steht in runden Klammern der untersuchte Wert.
Es folgt dann ein Block mit geschweiften Klammern. Innerhalb des Blocks kennzeichnen die Zeilen mit case … : die verschiedenen Fälle (englisch: cases). Es wird von oben nach unten geprüft, ob der Wert mit einem dieser Fälle übereinstimmt. Trifft dies zu, dann werden alle folgenden Anweisungen bis zur nächsten break-Anweisung ausgeführt.
Falls der Benutzer Italien eingibt, wird also als Hauptstadt Rom geliefert. Anschließend wird der switch-Block verlassen.
Falls der Benutzer England eingibt, wird als Hauptstadt London geliefert, da danach erst die nächste break-Anweisung folgt. Dasselbe trifft für Wales und Schottland zu. Sie haben also mit switch … case die Möglichkeit, mehrere Fälle übersichtlich zu vereinigen.
Trifft keiner der Fälle zu, können Sie mit default: alle restlichen Fälle abfangen. Ähnlich wie bei einem if ohne else muss es diesen Fall allerdings nicht zwingend geben.
Sie können mit switch … case eine Zahl oder, wie in diesem Fall, eine Zeichenkette untersuchen. Es ist nicht möglich, Fälle mit Zahlenbereichen anzugeben, wie z. B. case < 10: oder case >=10 &&<=20:.
Ein Hinweis zum Thema Verzweigungen
Sie sollten versuchen, nur die Programmteile innerhalb einer Verzweigung anzuordnen, die sich tatsächlich unterscheiden. Anders ausgedrückt: Sollte es eine Anweisung geben, die in jedem der Zweige steht, so hat sie nichts in der Verzweigung zu suchen. Sie sollte davor oder danach notiert werden.