Feb 2009

Javascript-Programmierung: Anweisungen und Kontrollstrukturen

 
 

Erst Konstrollstrukturen führen zu dynamischen Seiten, indem sie den Ablauf des Programms steuern – sie brechen die linare zeilenweise Ausführung der Anweisungen auf, erlauben das Überspringen von Anweisungsblöcken oder kontrollieren die wiederholte Ausführung von Anweisungen. Aus der Kombination von Kontrollstrukturen und Zuweisungen entstehen komplexer Abläufe.

Es gibt zwei grundlegende Methoden, den Programmfluss zu steuern:

  • Verzweigungen
  • Schleifen

Die if-Bedingung ist meistens ein Vergleich zweier Werte oder Variablen. Werden Zeichenketten miteinander vergleichen, gilt die lexikalische Ordnung.

Bedingungen

if (Bedingung) {                         while (Bedingung) {
   Anweisungen;                             Anweisungen; 
}                                        }

if (Bedingung) {                         do {
   Anweisungen;                              Anweisungen; 
} else {                                 } while (Bedingung);
   Anweisungen; 
}

for (Anweisung; Bedingung; Anweisung) {
   Anweisung
}

Bedingungen aller Art steuern das Programm – Anweisungen wie if()…else, for, switch, while und do…while beruhen auf Bedingungen, die innerhalb der Anweisungen abgefragt werden. Bedingung werden mit Vergleichsoperatoren und logischen Operatoren formuliert.

Die Bedingung muss immer in runden Klammern notiert werden, ansonsten kommt es zu einem Syntax-Fehler:

Fehler: missing ( before condition in FireFox, Fehler: '(' erwartet in Internet Explorer und Parse Error in Safari. Internet Explorer und Safari können die Zeile mit dem Fehler nicht korrekt lokalisieren.

Hinweis: Die häufigste Fehlerursache liegt beim Gleichheitszeichen des Vergleichs (==), wenn anstelle des Vergleichs (==) eine Zuweisung (=) geschrieben wird. Dabei entsteht kein Syntaxfehler, sondern die Zuweisung wird tatsächlich durchgeführt, so dass die Bedingung immer true liefert.

Die Frage nach der Existenz eines Objekts gehört zu den fundamentalen Bedingungen, die in fast allen Skripten gebraucht werden.

if (document.getElementById('myId')) {
   …
}

Die if-Abfrage prüft, ob ein Element mit der id myId existiert.

Prüfen, ob eine Methode in einem Browser implementiert ist:

if (document.getElementById) {
   …
}

Bedingte Ausführung: if () … else

if (Bedingung) {       
   Anweisungen1          
} else { 
   Anweisungen2
} 

In if ()…else-Anweisungen werden Anweisungen ausgeführt, wenn eine Bedingung wahr ist, der optionale else-Zweig wird ausgeführt, wenn die Bedingung nicht wahr ist. Die Bedingung muss dabei stets in runde Klammern gesetzt werden, damit kein Syntaxfehler entsteht.

if (zahl > 99) {                       if (zahl > 99) {
   alert(zahl + ' ist zu groß!');          alert(zahl + ' ist zu groß!');
}                                       } else {
                                           alert(zahl + ' ist zu klein!');
                                        }

Ob die Bedingung in der runden Klammer der if-Anweisung wahr oder falsch ist, wird anhand der Boole'schen Operationen festgestellt. Wenn bei der Boole'schen Operation true herauskommt, werden die Anweisungen innerhalb des Blocks in den geschweiften Klammern ausgeführt, wenn die Operation false liefert, werden die Anweisungen innerhalb des Blocks übersprungen. Auch eine Alternative kann gestellt werden.

Die Bedingung kann jeder Javascript-Ausdruck sein, der zu true oder false entwickelt werden kann. Die Anweisungen können beliebige Javascript-Anweisungen sein, insbesondere auch tiefer verschachtelte Anweisungen.

Wenn mehr als eine Anweisung im if- oder else-Zweigs ausgeführt werden sollen, müssen sie in geschweifte Klammern gesetzt werden, aber es gilt als gute Praxis, auch einzelne Anweisungen innerhalb des if- und else-Zweigs in geschweifte Klammern zu setzen.

Bei komplexen Bedingungen entstehen tief verschachtelte if() … else-Anweisungen.

if (isNaN(zahl)) {
   alert('Ihre Eingabe ' + zahl + ' ist keine Zahl!');
} else {
   if (zahl < 50) {
      alert(zahl + ' ist zu klein!');
   } else if (zahl > 50) {
      alert(zahl + ' ist zu groß');
   } else {
      alert('Das ist richtig!');
   }
}

Die erste Abfrage prüft, ob die Eingabe eine Zahl ist und gibt einen Hinweis aus, wenn dies nicht der Fall ist. Der else-Zweig verzweigt in drei Fälle:

  1. Die Zahl ist kleiner als 50,
  2. die Zahl ist größer als 50,
  3. wenn die Zahl weder kleiner noch größer als 50 ist, muss es sich um die gesuchte Zahl handeln, so dass die Abfrage if (zahl == 50) entfallen kann.

Komplexe geschachtelte if-Anweisungen sind schwer nachvollziehbar und verschlechtern die Lesbarkeit des Skripts. Bei einer langen Liste von Alternativen macht es Sinn, zu prüfen, ob eine switch-Anweisung die Steuerung nicht einfacher gestalten kann. Auf jeden Fall aber gilt die Empfehlung: Halte den Code links!

Der Ternary-Operator

Der Ternary-Operator ist eine kompakte Schreibweise der if…else-Anweisung. Anstelle von

var wert = null;
if (isNaN(zahl)) {
   wert = 0; 
} else {
   wert = 50;
}

reicht eine Zeile

var wert = isNaN(zahl) ? 0 : 50;

Das liest sich: Wenn die Variable zahl keine Zahl ist gib, gib 0 zurück und 50 sonst. Der Ternary-Operator spart bei einfachen if…else-Anweisungen ein paar Zeilen und das Erzeugen einer neuen Variablen – trägt also zur Übersichtlichkeit und Lesbarkeit des Skriptcodes bei.

Bedingte Ausführung: switch

switch (Ausdruck) {
   case label1: 
      Anweisungen; 
      break;
   case label2: 
      Anweisungen; 
      break; 
   ...
   default: Anweisungen;
} 

Eine switch-Anweisung vergleicht den Wert der Bedingung mit dem Wert, der neben jeder case-Marke aufgeführt ist. Wenn ein Treffer verzeichnet wird, führt das Programm die Anweisungen des case-Labels aus. default trifft auch jeden Wert zu, der nicht von einem der Filter zuvor abgefangen wurde und wird darum am Ende der switch-Anweisung notiert. break beendet die switch-Anweisung, so dass die folgenden Anweisungen nicht abgearbeitet werden.

Nur die switch-Anweisung benötigt die geschweiften Klammern. Ein sauber formatierter Code sorgt dafür, dass die switch-Anweisung besser lesbar ist.

switch (auswahl) {
   case "Äpfel": 
      alert(auswahl + ' , 1,75€');
      break;
   case "Birnen": 
      alert(auswahl + ' , 2,70€');
      break;
   case "Pflaumen": 
      alert(auswahl + ' , 3,05€');
      break;

   default: 
      alert(auswahl + ' haben wir leider nicht im Angebot');
   }
}

Die Schlüsselwort case ist eine Sprungmarke – ein „label“ –, das eine Stelle im Code markiert, an der die Ausführung des Programms beginnt, wenn der Ausdruck in der switch-Anweisung dem Wert der Sprungmarke entspricht.

Das Schlüsselwort default ist eine Sprungmarke, die alle Fälle abfängt, in denen keine der Bedingungen zutrifft.

Das Schlüsselwort break ist eine Anweisung, den switch-Block sofort zu verlassen und am Ende des Blocks mit der Ausführung fortzufahren. Wenn break nicht am Ende jeder case-Marke steht, fällt die Prüfung im wahrsten Sinne des Wortes durch: Auch wenn z.B. die erste case-Marke zutrifft, werden die Anweisungen der folgenden case-Marke ausgeführt. Steht dort ebenfalls kein break, werden auch hier die Anweisungen ausgeführt und am Ende auch noch die Anweisungen der default-Marke.

Trotzdem gibt es auch Fälle, in denen es Sinn macht, die break-Anweisung zu unterlassen, z.B. um mehrere Fälle mit demselben Block von Anweisungen zu behandeln.

switch(parseInt(zahl)) {
   case 0:
   case 1:
   case 2:
      alert(zahl + ' war zu klein');
      break;
   case 3: 
      alert('Genau ' + zahl + ' war richtig!');
      break;
   case 4:
   case 5:
      alert(zahl + ' war zu groß');
      break;
   default:
   alert('Das war völlig daneben oder gar keine Zahl!');
}

Wenn die Eingabe 0, 1, oder 2 war, wird der Anweisungsblock der case-Marke 2 ausgeführt, ebenso wie der Anweisungsblock der case-Marke 5 ausgeführt wird, wenn die Eingabe 4 oder 5 lautet.

Dieselbe Wirkung hätte auch eine if()…else-Anweisung erzielt:

if (parseInt(zahl) >= 0 && parseInt(zahl) < 3) {
   alert(zahl + ' war zu klein');
} else if (parseInt(zahl) > 3 && parseInt(zahl) <= 5) {
   alert(zahl + ' war zu groß');
} else if (parseInt(zahl) === 3) {
   alert('Genau ' + zahl + ' war richtig!');
} else {
   alert('Das war völlig daneben oder gar keine Zahl!');
}

Die switch-Anweisung kann gegen eine if…else-Anweisung ausgetauscht werden. Wenn mehr als zwei oder drei Alternativen bestehen, ist die switch-Anweisung meistens einfacher in der Handhabung und auch effizienter, da sie nicht die Bedingung nicht für jede Option testen muss.

Der Wert, der auf das Schlüsselwort case folgt, kann seit Javascript Version 1.3 auch ein Ausdruck sein. case-Anweisungen testen, ob der Ausdruck identisch ist und nicht, ob der Ausdruck gleich ist. Das bedeutet, dass ihr Wert denselben Wert und Typ liefern muss wie der Ausdruck der switch-Anweisung. Wenn das Ergebnis der switch-Bedingung also immer bei der default-Aktion endet, stimmen meist die Typen der entwickelten Ausdrücke nicht überein – im vorangegangenen Beispiel wäre das der Fall, wenn die Variable zahl nicht in einen Integer verwandelt worden wäre: Der Wert eines INPUT-Elements ist immer ein String, auch wenn eine Zahl eingegeben wird.

   


Copyright © 2000 - 2010 Media Engineering Alle Rechte vorbehalten
Design + Programmierung Media Engineering U. Häßler 47506 Neukirchen-Vluyn • Impressum und Nutzungsbestimmungen