JavaScript unterstützt einen kompakten Satz von Anweisungen zur Flusskontrolle. Diese können eingesetzt werden, um Websites interaktiv zu gestalten. Dieses Kapitel bietet eine Übersicht zu diesen Anweisungen.
Jeder Ausdruck ist auch eine Anweisung. Das Kapitel Ausdrücke und Operatoren stellt hierzu mehr Informationen bereit.
Zur Trennung von Anweisungen wird das Semikolon (;) verwendet. Die JavaScript-Referenz informiert darüber genauer.
Blockstruktur
Anweisungen werden durch Anweisungsblöcke gruppiert und zusammengefasst. Ein Anweisungsblock wird durch geschweifte Klammern festgelegt:
{
Anweisung_1;
Anweisung_2;
.
.
.
Anweisung_n;
}
Beispiel
Anweisungsblöcke werden vorwiegend in Verbindung mit Anweisungen zum Kontrollfluss eingesetzt (z. B. if, for, while).
while (x < 10){
x++;
}
Bei diesem Beispiel ist { x++; } der Anweisungsblock.
Wichtig: JavaScript grenzt die Sichtbarkeit (Scope) von Blöcken nicht ab. Variablen, die innerhalb eines Blocks deklariert werden, sind innerhalb der Funktion oder des Skripts sichtbar und bleiben auch innerhalb dieses Bereichs erhalten. Mit anderen Worten: Anweisungsblöcke erzeugen keinen seperaten Sichtbarkeitsbereich. Obwohl es auch eigenständige Blockanweisungen (standalone) gibt und diese zur Syntax gehören, sollte man auf deren Einsatz besser verzichten, da sie nicht auf dieselbe Weise funktionieren wie z. B. bei C oder Java.
Beispiel:
var x = 1;
{
var x = 2;
}
alert(x); // Ausgabe: 2
Die Ausgabe ist hier 2, weil sich die Anweisung var x innerhalb des Anweisungsblocks im selben Sichtbarkeitsbereich befindet, wie die andere var x-Anweisung außerhalb des Anweisungsblocks. Bei C oder Java wäre die Ausgabe 1.
Bedingte Anweisungen
Bei einer bedingten Anweisung wird ein Satz von Befehlen ausgeführt,
wenn eine bestimmte festgelegte Bedingung erfüllt ist. JavaScript kennt
hierfür zwei verschiedene Anweisungen: if...else und switch.
if...else-Anweisung
Die if Anweisung sollte eingesetzt werden, wenn
bestimmte Anweisungen ausgeführt werden sollen, falls eine logische
Bedingungen erfüllt ist. Zusätzlich kann ein optionaler else-Abschnitt festgelegt werden, dessen Anweisungen ausgeführt werden, falls die Bedingung nicht erfüllt ist. Die Syntax einer if Anweisung ist wie folgt:
if (Bedingung)
Anweisung_1
[else
Anweisung_2]
Die Bedingung kann jeder Ausdruck sein, der zu true oder false evaluiert. Wenn die Bedingung true ist, wird Anweisung_1 ausgeführt, andernfalls wird Anweisung_2 ausgeführt. Anweisung_1 und Anweisung_2 können für beliebige Anweisungen stehen; auch weitere verschachtelte if-Anweisungen könnten an dieser Stelle eingesetzt werden.
Darüber hinaus ist es mit Hilfe von else if möglich, mehrere Bedingungen nacheinander zu überprüfen (Verzweigung):
if (Bedingung)
Anweisung_1
[else if (Bedingung_2)
Anweisung_2]
...
[else if (Bedingung_n_1)
Anweisung_n_1]
[else
Anweisung_n]
Sollen mehrere Anweisungen ausgeführt werden, müssen sie innerhalb eines Anweisungsblocks ({ ... })
stehen. Es ist gute Praxis, die Blöcke immer anzugeben, auch wenn sie
für einzelne Anweisungen nicht zwingend notwendig sind. Insbesondere bei
verschachtelten if-Anweisungen wird hierdurch die Lesbarkeit verbessert.
if (Bedingung) {
Anweisungen_1
} else {
Anweisungen_2
}
Auch ist es empfehlenswert keine Zuweisungen an der Stelle für die Bedingung vorzunehmen, weil diese aufgrund des Gleichzeichens leicht mit Vergleichen verwechselt werden können. Der folgende Code sollte also nicht verwendet werden:
if (x = y) {
/* do the right thing */
}
Wenn man eine Zuweisung in einem bedingten Ausdruck vornehmen möchte, sollte diese in zusätzliche Klammern eingeschlossen werden. Zum Beispiel:
if ((x = y)) {
/* mach das Richtige */
}
Die folgenden Werte evaluieren zu false:
falseundefinednull0NaN- die leere Zeichenkette (
"")
Alle anderen Werte, einschließlich aller Objekte, evaluieren zu true, wenn sie als Bedingung angegeben werden.
Vorsicht: Die primitiven booleschen Werte wie true und false sollten nicht mit den Werten true und false des booleschen Objekts (Boolean) verwechselt werden.
Zum Beispiel:
var b = new Boolean(false);
if (b) // diese Bedingung evaluiert zu true
Beispiel
Beim folgenden Beispiel liefert die Funktion checkData den Wert true, wenn die Anzahl der Zeichen eines Text-Objekts dem Wert 3 entspricht. Andernfalls wird eine Alarm-Nachricht ausgegeben und false zurückgegeben.
function checkData() {
if (document.form1.threeChar.value.length == 3) {
return true;
} else {
alert("Bitte genau 3 Zeichen eingeben. " +
document.form1.threeChar.value + " is not valid.");
return false;
}
}
switch-Anweisung
Bei der switch-Anweisung wird ein Ausdruck ausgewertet
und das Ergebnis mit den unterschiedlichen Ausdrücken der case-Labels
verglichen (Fallunterscheidung). Stimmen die Werte überein, werden die
Anweisungen des entsprechenden case-Abschnitts ausgeführt.
Beispiel:
switch (Ausdruck) {
case Label_1:
Anweisung_1
[break;]
case Label_2:
Anweisung_2
[break;]
...
default:
Anweisung_falls_kein_case_Ausdruck_passt
[break;]
}
Bei diesem Skript wird zuerst nach einem case-Abschnitt
gesucht dessen Wert mit dem Wert des in Klammern spezifizierten
Ausdrucks übereinstimmt. Wird ein solcher Wert gefunden, werden die
Anweisungen des case-Abschnitts ausgeführt. Sollte keiner der Werte mit dem Wert des Ausdrucks übereinstimmen, wird nach einem default-Abschnitt
gesucht und falls vorhanden, die Kontrolle an diesen übergeben und die
entsprechenden Anweisungen ausgeführt. Falls kein default-Abschnitt vorhanden ist, wird die Ausführung hinter der switch-Anweisung fortgesetzt. Der Konvention nach sollte der default-Abschnitt an letzter Stelle stehen, jedoch ist er keine Pflicht.
Die optionale break-Anweisung innerhalb jedes case-Abschnitts bewirkt den Abbruch der switch-Anweisung. Die Ausführung wird dann hinter der switch-Anweisung fortgesetzt. Wenn break nicht angegeben ist, findet kein Abbruch statt und die Anweisungen folgender case-Abschnitte werden ebenfalls ausgeführt.
Beispiel
Beim folgenden Beispielcode evaluiert fruittype zu "Bananen". Daraufhin wird eine Übereinstimmung beim case-Abschnitt "Bananen" gefunden und die Anweisungen dieses Abschnitts werden ausgeführt. Anschließend wird die switch-Anweisung an der Stelle des break verlassen und die Ausführung hinter dem switch-Block fortgesetzt. Wenn kein break innerhalb des Bananen-Abschnitts angegeben wäre, würde der Abschnitt "Kirschen" ebenfalls (bis zu break) ausgeführt werden.
switch (fruittype) {
case "Orangen":
document.write("Orangen kosten 0.59 EUR das Pfund.<br>");
break;
case "Birnen":
document.write("Birnen kosten 0.32 EUR das Pfund.<br>");
break;
case "Bananen":
document.write("Bananen kosten 0.48 EUR das Pfund.<br>");
break;
case "Kirschen":
document.write("Kirschen kosten 3.00 EUR das Pfund.<br>");
break;
case "Mangos":
case "Papayas":
document.write("Mangos und Papayas kosten 2.79 EUR das Pfund.<br>");
break;
default:
document.write("Entschuldigung, " + fruittype + "sind ausverkauft.<br>");
}
document.write("Darf es sonst noch etwas sein?<br>");
Schleifen-Anweisungen
Eine Schleife ist ein Satz von Befehlen, die solange wiederholt
ausgeführt werden, bis eine bestimmte Bedingung erfüllt ist. Javascript
unterstützt die Anweisungen for, do while und while,
sowie Labels (Labels sind nicht direkt Schleifenanweisungen, werden
aber sehr oft mit diesen zusammen verwendet). Zusätzlich können die
beiden Anweisungen break und continue zum Einsatz kommen.
Eine weitere Anweisung ist for...in, welche ebenfalls wiederholt Anweisungen ausführt, jedoch zur Manipulation von Objekten verwendet wird. Siehe Anweisungen zur Objekt-Manipulation.
Die Schleifen-Anweisungen sind:
- for-Anweisung
- do...while-Anweisung
- while-Anweisung
- label-Anweisung
- break-Anweisung
- continue-Anweisung
for-Anweisung
Eine for-Schleife führt wiederholt Anweisungen aus, bis
eine festgelegte Bedingung zu false evaluiert. Die Syntax der
for-Schleife ist ähnlich wie bei Java und C:
for ([Initialisierungsausdruck]; [Bedingung]; [Inkrementierungsausdruck])
Anweisung
Wenn eine for-Schleife ausgeführt wird, passiert folgendes:
- Der
Initialisierungsausdruckwird (falls angegeben) ausgeführt. Der Ausdruck initialisiert für gewöhnlich eine oder mehrere einfache Variablen, die zur Schleifenzählung verwendet werden. Die Syntax erlaubt jedoch Anweisungen beliebiger Komplexität. Auch Variablen-Zuweisungen sind erlaubt. - Der Ausdruck
Bedingungwird ausgewertet. Wenn der Werttrueist, wird dieAnweisungausgeführt. Wenn der Wert derBedingungfalseist, wird die Schleife abgebrochen. Fehlt der AusdruckBedingungkomplett, wird angenommen, dass der Wert derBedingungtrueist. - Die
Anweisungwird ausgeführt. Bei mehreren Anweisungen muss eine Blockanweisung ({ ... }) zur Gruppierung verwendet werden. - Der
Inkrementierungsausdruck(üblicherweise wird die Zählvariable inkrementiert), falls angegeben, wird ausgeführt und der nächste Schleifendurchlauf gestartet (Schritt 2). Dies wird solange wiederholt, bis dieBedingungnicht mehr erfüllt ist.
Beispiel
Die Funktion im folgenden Code enthält eine for-Schleife, welche die Anzahl der ausgewählten Optionen in einer Liste zählt. Die for-Schleife deklariert die Variable i und initialisiert sie mit dem Wert 0. Die Schleife überprüft, ob i kleiner ist als die Anzahl der verfügbaren Optionen des select-Objekts,
welches die Auswahl mehrerer Optionen erlaubt. Solange dies zutrifft
wird wiederholt der Anweisungsblock mit der if-Anweisung ausgeführt und
der Wert der Variablen i nach jedem Schleifendurchlauf um 1 erhöht.
<script type="text/javascript">
function howMany(selectObject) {
var numberSelected = 0;
for (var i = 0; i < selectObject.options.length; i++) {
if (selectObject.options[i].selected)
numberSelected++;
}
return numberSelected;
}
</script>
<form name="selectForm">
<p>
<strong>Choose some music types, then click the button below:</strong>
<br/>
<select name="musicTypes" multiple="multiple">
<option selected="selected">R&B</option>
<option>Jazz</option>
<option>Blues</option>
<option>New Age</option>
<option>Classical</option>
<option>Opera</option>
</select>
</p>
<p>
<input type="button" value="How many are selected?"
onclick="alert ('Number of options selected: ' + howMany(document.selectForm.musicTypes))"/>
</p>
</form>
do...while Anweisung
Bei der do...while-Anweisung wird die Ausführung solange wiederholt bis eine bestimmte Bedingung zu false evaluiert. Die Syntax einer do...while-Anweisung ist wie folgt:
do
Anweisung
while (Bedingung);
Die Anweisung wird einmal ausgeführt bevor die Bedingung überprüft
wird. Um mehrere Anweisungen auszuführen, muss eine Blockanweisung zur
Gruppierung eingesetzt werden. Wenn der Wert der Bedingung true
ist, wird die Anweisung erneut ausgeführt. Die Bedingung wird nach
jedem Durchlauf überprüft und die Schleife abgebrochen, wenn die
Bedingung nicht mehr erfüllt ist.
Beispiel
Beim folgenden Beispiel wird zuerst ein Schleifendurchlauf durchgeführt. Anschließend wird die Bedingung überprüft und solange weitere Schleifendurchläufe durchgeführt, bis i nicht mehr kleiner als 5 ist.
do {
i += 1;
document.write(i);
} while (i < 5);
while-Anweisung
Eine while-Anweisung führt Anweisungen solange
wiederholt aus wie eine bestimmte Bedingung zu true evaluiert. Eine
while Anweisung sieht wie folgt aus:
while (Bedingung)
Anweisung
Wenn die Bedingung nicht mehr erfüllt ist, stoppt die Ausführung der Anweisung und die Ausführung wird hinter der Schleife fortgesetzt.
Die Bedingung wird gleich zu Beginn vor der Ausführung der Anweisung überprüft. Wenn die Bedingung erfüllt ist, wird die Anweisung ausgeführt und die Bedingung erneut überprüft. Wenn die Bedingung nicht erfüllt ist, wird die Schleife abgebrochen und die Ausführung hinter der Schleife fortgesetzt.
Auch bei der while-Schleife müssen mehrere Anweisungen durch einen Anweisungsblock ({ ... }) gruppiert werden.
Beispiel 1
Die folgende while-Schleife wird ausgeführt, solange n kleiner als 3 ist:
n = 0;
x = 0;
while (n < 3) {
n++;
x += n;
}
Mit jeder Iteration wird die Variable n inkrementiert und der Wert zu x hinzuaddiert. Daher nehmen x und n im Verlauf die folgenden Werte an:
- Nach dem ersten Durchlauf: n = 1 und x = 1
- Nach dem zweiten Durchlauf: n = 2 und x = 3
- Nach dem dritten Durchlauf: n = 3 und x = 6
Nachdem der dritte Durchlauf abgeschlossen ist, ist die Bedingung n < 3 nicht mehr erfüllt und die Schleife wird abgebrochen.
Beispiel 2
Man sollte unbedingt darauf achten, keine Endlos-Schleifen zu
programmieren, also sicherstellen, dass die Bedingung früher oder später
nicht mehr erfüllt ist, sodass die Schleife abbricht. Die Anweisungen
des folgenden Codes werden unendlich wiederholt ausgeführt, weil die
Bedingung niemals zu false evaluiert:
while (true) {
alert("Hello, world");
}
Label-Anweisungen
Ein Label ist ein Bezeichner, der eine Stelle markiert, die als
Sprungziel dient. Zum Beispiel kann mit einem Label eine Schleife
markiert und anschließend mit Hilfe von break oder continue die Schleife unterbrochen oder beim nächsten Durchlauf fortgesetzt werden.
Syntax:
Label :
Anweisung
Der Wert von Label kann ein JavaScript-Bezeichner sein, der jedoch keines der reservierten Wörter von JavaScript sein darf. Anweisung kann für beliebige Anweisungen stehen.
Beispiel
Bei diesem Beispiel markiert das Label markLoop eine while-Schleife:
markLoop:
while (theMark == true) {
doSomething();
}
break-Anweisung
Die break-Anweisung wird in Verbindung mit Schleifen, switch-Anweisungen oder mit Labels zum Abbruch eingesetzt.
- Wenn break ohne ein Label verwendet wird, terminiert es das innerste while, do-while, for, oder switch und gibt die Kontrolle an die dahinterstehende Anweisung weiter.
- Wenn break mit einem Label eingesetzt wird, terminiert es die angegebende Label-Anweisung.
Die Syntax von break-Anweisungen ist wie folgt:
break;break Label;
Die erste Form terminiert die innerste Schleife oder switch-Anweisung. Die zweite Form terminiert die angegebene Label-Anweisung.
Beispiel 1:
Beim folgenden Beispiel wird solange über die Elemente eines Arrays
iteriert, bis der index eines Elements gefunden wird, dessen Wert derWert entspricht:
for (i = 0; i < a.length; i++) {
if (a[i] == derWert)
break;
}
Beispiel 2: Abbruch und Sprung zu einem Label
var x = 0;
var z = 0
labelCancelLoops: while (true) {
console.log("Outer loops: " + x);
x += 1;
z = 1;
while (true) {
console.log("Inner loops: " + z);
z += 1;
if (z === 10 && x === 10) {
break labelCancelLoops;
} else if (z === 10) {
break;
}
}
}
continue-Anweisung
Mit der continue-Anweisung wird ein Sprung zum nächsten Schleifendurchlauf veranlasst.
- Wenn
continueohne ein Label eingesetzt wird, bricht es den aktuellen Durchlauf der innerstenwhile-,do-while-oderfor-Anweisung ab und die Ausführung wird bei der nächsten Iteration fortgesetzt. Im Gegensatz zubreakwird beicontinuedie Schleife nicht komplett abgebrochen, sondern nur der aktuelle Durchlauf der Schleife. Bei einerwhile-Schleife wird ein Sprung zurück zur Bedingung durchgeführt. Bei einerfor-Schleife bewirktcontinueeinen Sprung zum Inkrementierungsausdruck. - Steht nach
continueein Label, bewirkt es einen Sprung zu diesem Label.
Die Syntax der continue-Anweisung ist wie folgt:
continuecontinueLabel
Beispiel 1
Das folgende Beispiel zeigt eine while-Schleife mit einer continue-Anweisung, die ausgeführt wird, wenn i den Wert 3 besitzt. Im Verlauf der Ausführung nimmt n die Werte 1, 3, 7 und 12 an.
i = 0;
n = 0;
while (i < 5) {
i++;
if (i == 3)
continue;
n += i;
}
Beispiel 2
Eine Anweisung mit dem Label checkiandj enthält eine weitere Anweisung mit dem Label checkj. Wenn continue erreicht ist, bricht das Skript die aktuelle Iteration von checkj ab und startet die nächste Iteration. Jedes Mal, wenn continue erreicht ist, wird checkj erneut durchlaufen, solange bis die Bedingung der if-Anweisung zu false evaluiert. Wenn false zurückgegeben wird, wird der Rest des Codes von checkiandj bis zum Ende ausgeführt und checkiandj wiederholt, bis die zugehörige Bedingung zu false evaluiert. Wenn false zurückgegeben wird, wird die Ausführung bei der Anweisung hinter checkiandj fortgesetzt.
Wenn bei continue das Label checkiandj angegeben wäre, würde das Skript am Anfang der checkiandj-Anweisung fortgesetzt.
checkiandj :
while (i < 4) {
document.write(i + "<br/>");
i += 1;
checkj :
while (j > 4) {
document.write(j + "<br/>");
j -= 1;
if ((j % 2) == 0)
continue checkj;
document.write(j + " is odd.<br/>");
}
document.write("i = " + i + "<br/>");
document.write("j = " + j + "<br/>");
}
Anweisungen zur Objekt-Manipulation
JavaScript benutzt die Anweisungen for...in, for each...in, und with zur Manipulation von Objekten.
for...in-Anweisung
Die Anweisung for...in iteriert eine bestimmte Variable über alle Eigenschaften eines Objekts. Bei jedem Schleifendurchlauf wird Variable der Name der Eigenschaft zugewiesen. Die Anweisungen werden für jede vorhandene Eigenschaft einmal ausgeführt.
Syntax:
for (Variable in Objekt) {
Anweisungen
}
Beispiel
Die folgende Funktion nimmt ein Objekt als Argument und den Namen des Objekts entgegen. Anschließend wird mit Hilfe von for...in über alle Objekteigenschaften iteriert und ein String mit dem Namen und dem Wert der Eigenschaft zurückgegeben.
function dump_props(obj, obj_name) {
var result = "";
for (var i in obj) {
result += obj_name + "." + i + " = " + obj[i] + "<br>";
}
result += "<hr>";
return result;
}
Bei einem Objekt automobil mit den Eigenschaften hersteller und modell wäre das Ergebnis:
automobil.hersteller = Ford
automobil.modell = Mustang
Arrays
Obwohl es sinnvoll erscheinen mag, eine for...in-Anweisung zu benutzen, um über die Elemente eines Arrays zu iterieren, weil die for...in-Anweisung
zusätzlich zu den Array-Elementen auch benutzerdefinierte Eigenschaften
und Methoden erfasst, sollte besser eine normale for-Schleife
benutzt werden, um über Array-Elemente zu interieren, da bei
benutzerdefinierten Methoden nicht nur ein numerischer Index, sondern
auch der Name der benutzerdefinierten Eigenschaften oder Methoden
zurückgegeben wird.
for each...in Anweisung
for each...in ist eine Schleifenanweisung, die mit JavaScript 1.6 eingeführt wurde. Sie ist ähnlich wie for...in, aber iteriert über die Werte von Objekt-Eigenschaften und nicht über die Namen.
var sum = 0;
var obj = {prop1: 5, prop2: 13, prop3: 8};
for each (var item in obj) {
sum += item;
}
print(sum); // gibt 26 aus, also die Summe von 5+13+8
Kommentare
Kommentare sind Bemerkungen der Autorin/des Autors, welche die Funktion von Code beschreiben. Kommentare werden vom Interpreter ignoriert. JavaScript unterstützt die Syntax für Kommentare im Stil von Java und C++:
- Einzeilige Kommentare werden durch doppelte Schrägstriche (//) eingeleitet.
- Kommentare über mehrere Zeilen werden in /* und */ eingeschlossen.
Beispiel
Der folgende Code demonstriert die beiden Varianten zur Kennzeichnung von Kommentaren:
// Dies ist ein einzeiliger Kommentar.
/* Dies ist ein mehrzeiliger Kommentar.
Er kann sich über beliebig viele Zeilen erstrecken
und beliebige Zeichen enthalten. */
Anweisungen zur Ausnahmebehandlung (Exceptions)
Mit der Anweisung throw wird eine Ausnahmenbehandlung eingeleitet und Werte von Ausdrücken ausgeworfen. Außerdem lässt sich mit Hilfe der try...catch-Anweisung auf Ausnahmen reagieren.
Mit try...catch können auch Java-Ausnahmen behandelt werden (Vorsicht: bug 391642 ). Unter Handling Java Exceptions in JavaScript und JavaScript to Java Communication wird genauer auf das Thema eingegangen.
Typen von Ausnahmen
Nahezu jedes Objekt kann in JavaScript ausgeworfen werden, jedoch werden nicht alle Objekte auf dieselbe Weise erstellt. Obwohl es üblich ist, dass Ziffern oder Zeichenketten als Error ausgeworfen werden, ist es weit mehr effektiver, einen der Ausnametypen zu benutzen, die speziell für diesen Zweck entwickelt wurden.
throw-Anweisung
Die throw-Anweisung wird eingesetzt, um eine Ausnahmebehandlung
einzuleiten und einen Ausdruck auszuwerfen. Der Ausdruck, dessen Wert
ausgeworfen werden soll, wird hinter throw angegeben:
throw Ausdruck;
Der Ausdruck muss nicht von einem speziellen Typ sein, sondern es kann jede Art von Ausdruck benutzt werden. Der folgende Code wirft verschiedene Ausnahmen mit unterschiedlichen Typen aus:
throw "Error2";
throw 42;
throw true;
throw {toString: function() { return "Ich bin ein Objekt!"; } };
catch-Block auf die Eigenschaften dieses Objekts zugegriffen werden. Beim folgenden Beispiel wird ein Objekt myUserException mit dem Typ UserException erstellt und dieses in einer throw-Anweisung benutzt.// Erstellen eines Objekt-Typs UserException
function UserException (message){
this.message=message;
this.name="UserException";
}
// Konvertieren der Ausnahme zu einem String,
// wenn sie als String benutzt wird (z .B. von der Error-Konsole)
UserException.prototype.toString = function (){
return this.name + ': "' + this.message + '"';
}
// Erstellen einr Instanz des Objekt-Typs und Auswurf
throw new UserException("Value too high");
try...catch-Anweisung
Bei der try...catch-Anweisung wird ein Block von
Anweisungen "ausprobiert" und auf gegebenenfalls auftretende Ausnahmen
reagiert. Wenn eine Ausnahme ausgeworfen wird, wird sie von der try...catch-Anweisung abgefangen.
Die try...catch-Anweisung besteht aus einem try-Block,
welcher eine oder mehrere Anweisungen enthält und einem oder mehreren
catch-Blöcken, die Anweisungen enthalten und jeweils bestimmen, was beim
Auftreten einer bestimmten Ausnahme getan werden soll. Man möchte in
der Regel, dass der try-Block erfolgreich ausgeführt wird, doch falls
Fehler auftreten, entsprechend mit den catch-Anweisungen darauf reagieren. Sobald eine Ausnahme durch den Code im try-Block
(oder eine Funktion, die im try-Block ausgeführt wird) ausgelöst wurde,
wird die Kontrolle an den catch-Block übergeben. Wenn keine Ausnahme im
try-Block ausgelöst wird, wird der catch-Block nicht ausgeführt. Der finally-Block wird nach dem try- und catch-Block ausgeführt, jedoch bevor der Code nach dem try...catch ausgeführt wird. Mit dem finally-Block werden in der Regel Aufräumarbeiten durchgeführt.
Beim folgenden Beispiel kommt eine try...catch-Anweisung
zur Anwendung. Es wird eine Funktion aufgerufen, die eine Zahl entgegen
nimmt und anhand dieser einen Monatsnamen aus einem Array auswählt.
Wenn der Wert keiner Monatszahl (1-12) entspricht, wird eine Ausnahme
ausgelöst, welche den Wert "InvalidMonthNo" auswirft und die Anweisungen im catch-Block setzen die monthName-Variable auf unknown.
function getMonthName (mo) {
mo=mo-1; // Adjust month number for array index (1=Jan, 12=Dec)
var months=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec");
if (months[mo] != null) {
return months[mo]
} else {
throw "InvalidMonthNo"
}
}
try {
// statements to try
monthName=getMonthName(myMonth) // function could throw exception
}
catch (e) {
monthName="unknown"
logMyErrors(e) // pass exception object to error handler
}
Der catch-Block
Mit dem catch-Block kann jede Ausnahme, die im try-Block ausgelöst wird, abgefangen werden.
catch (catchID) {
Anweisungen
}
Bei diesem catch-Block wurde ein Bezeichner catchID angegeben, welcher den Wert enthält, der von der throw-Anweisung
ausgeworfen wird. Diesen Bezeichner kann man benutzen, um Informationen
zu der ausgelösten Ausnahme zu erhalten. JavaScript erstellt diesen
Bezeichner, wenn der catch-Block zur Ausführung kommt. Der Bezeichner
bleibt nur für den catch-Block erhalten. Nachdem die Ausführung des
catch-Blocks beendet ist, kann auf den Bezeichner nicht mehr zugegriffen
werden.
Der folgende Code löst eine Ausnahme aus. Sobald die Ausnahme ausgelöst wird, wird der catch-Block ausgeführt.
try {
throw "myException" // löst Ausnahme aus
}
catch (e) {
// Anweisungen um auf die Ausnahme zu reagieren
logMyErrors(e) // Das Ausnahme-Objekt wird an eine Funktion übergeben
}
Der finally-Block
Der finally-Block enthält Anweisungen, die nach den try- und catch-Blöcken ausgeführt werden, jedoch bevor der Code hinter der try...catch-Anweisung
ausgeführt wird. Der Block wird unabhängig davon ausgeführt, ob eine
Ausnahme ausgelöst wurde oder nicht. Auch wenn gar kein catch-Block vorhanden ist, womit auf eine Ausnahme reagiert wird, wird der finally-Block ausgeführt.
Mit Hilfe des finally-Blocks kann man elegant auf Fehler in einem Skript reagieren. Zum Beispiel möchte man vielleicht Ressourcen wieder freigeben, die das Skript in Anspruch genommen hat, bevor ein Abbruch stattfindet. Beim folgenden Beispiel wird eine Datei geöffnet und Anweisungen ausgeführt, die mit der Datei arbeiten (serverseitiges Javascript erlaubt den Zugriff auf Dateien). Wenn eine Ausnahme ausgelöst wird während die Datei geöffnet ist, schließt der Code des finally-Blocks die Datei, bevor die Ausführung des Skripts abbricht.
openMyFile();
try {
writeMyFile(theData); // Hier könnte ein Fehler passieren
}catch(e){
handleError(e); // Fehlerbehandlung falls Fehler auftritt
}finally {
closeMyFile(); // In jedem Fall Datei schließen
}
Wenn der finally-Block einen Wert zurückgibt, ist dieser Wert der return-Wert des kompletten try-catch-finally-Blocks, unabhängig davon welche return-Werte die Funktionen in den try- und catch-Blöcken zurückgeben.
function f() {
try {
alert(0);
throw "bogus";
} catch(e) {
alert(1);
return true; // Dieser return-Wert wird zurückgehalten bis der finally-Block ausgeführt wurde
alert(2); // nicht erreichbar
} finally {
alert(3);
return false; // überschreibt das vorherige "return"
alert(4); // nicht erreichbar
}
// "return false" wird nun ausgeführt
alert(5); // nicht erreichbar
}
f(); // alert-Meldungen: 0, 1, 3 und "return false" wird ausgeführt
Verschachteln von try...catch-Anweisungen
Man kann eine oder mehrere try...catch-Anweisungen verschachteln. Wenn eine innere try...catch-Anweisungen keinen catch-Block hat, wird die einschließende try-catch-Anweisung auf eine Übereinstimmung überprüft.
Einsatz von Error-Objekten
Je nach Art des Fehlers kann es möglich sein, dass auf die Eigenschaften "name" und "message" zugegriffen werden kann, um detaillierte Informationen zu erhalten. Die Eigenschaft "name" enthält die Fehlerklasse (z. B. "DOMException" oder "Error") und die Eigenschaft "message" in der Regel genauere Informationen, als wenn man nur das Error-Objekt zu einem String konvertiert.
Wenn man selbst die Meldungen für Ausnahmen definieren möchte, um sich diese Eigenschaften zunutze zu machen (z. B. falls der catch-Block nicht zwischen System-Ausnahmen und selbst definierten Ausnahmen unterscheidet) kann man den Error-Konstruktor benutzen.
Zum Beispiel:
function doSomethingErrorProne () {
if (ourCodeMakesAMistake()) {
throw (new Error('Die Nachricht'));
} else {
doSomethingToGetAJavascriptError();
}
}
....
try {
doSomethingErrorProne();
}
catch (e) {
alert(e.name); // Alarm-Meldung: 'Error'
alert(e.message); // Alarm-Meldung: 'Eine Nachricht' oder eine JavaScript-Fehlermeldung)
}