vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Tag 9

JavaScript- Grundkurs

Wie man JavaScript einsetzt und was man so mit JavaScript anfangen kann, wissen Sie jetzt. Um aber richtig mit JavaScript programmieren zu können, um nicht bei jeder noch so kleinen JavaScript-Funktion mit Syntaxfehlern kämpfen zu müssen und um anspruchsvollere JavaScript-Funktionen programmieren zu können, müssen Sie mehr über die grundlegende JavaScript-Syntax lernen.

In dieser Hinsicht ist JavaScript nichts anderes als eine ganz normale höhere Programmiersprache, und viele Konzepte, die Sie heute am Beispiel von JavaScript kennen lernen werden, kann man auch in anderen Programmiersprachen wiederfinden. Leser, für die dieses Kapitel der Einstieg in die Programmierung ist, werden von dem hier Gelernten also auch beim Erlernen weiterer Programmierkapitel profitieren (wir denken hier vor allem an die dritte Woche). Umgekehrt werden sich Lesern, die bereits über Programmiererfahrung verfügen, schnell und ohne Probleme in die Programmierung mit JavaScript einarbeiten.

Die Themen im Einzelnen:

9.1 Variablen, Konstanten und Datentypen

Programme dienen der Verarbeitung von Daten, wobei es sich ebenso gut um Zahlen (3 oder 54) wie um Strings ("<p>Hallo JavaScript</p>") oder die Hintergrundfarbe einer Webseite handeln kann. Um aber sinnvoll mit Daten programmieren zu können, muss es eine Möglichkeit geben, wie man Daten in einem Programm zwischenspeichern kann.

Denken Sie nur daran, wie Sie eine Folge von Zahlen, beispielsweise 3 - 15 - 7 - 4 addieren. Sie addieren 3 und 15 behalten das Ergebnis im Kopf und addieren dann 7, speichern das Ergebnis wieder im Kopf, addieren 4 und haben im Kopf dann das Ergebnis (29, wenn mein Kopfrechnen mich nicht im Stich gelassen hat).

Variablen repräsentieren Daten

Wo aber kann der Rechner Werte zwischenspeichern? Richtig, im Arbeitsspeicher. Der Arbeitsspeicher besteht aus einer Folge von einzelnen Speicherzellen, die durchgehend nummeriert sind. Dies sind die sogenannten Speicheradressen. Will man einen Wert im Speicher ablegen, sucht man sich einen genügend großen Speicherplatz und merkt sich die Anfangsadresse sowie die Größe des Speicherplatzes. Das klingt kompliziert und es ist auch kompliziert. Deshalb nimmt uns der Interpreter die gesamte komplizierte Arbeit der Speicherverwaltung ab. Alles, was wir tun müssen, wenn wir Speicher zur Aufbewahrung von Daten benötigen, ist, uns Variablennamen auszudenken und diesen die Daten zuzuweisen.

Wenn Sie eine Variable definieren, reserviert der Compiler für diese Variable Speicher im Arbeitsspeicher des Computers und verbindet den Variablennamen mit diesem Speicher. Danach können Sie der Variablen Werte zuweisen oder den Wert der Variablen abfragen.

Wie könnte demnach die obige Aufsummierung als JavaScript-Code aussehen?

Listing 9.1: Auszug aus variablen.html

<body>

<h1>Variablen</h1>

<script type="text/javascript">
var summe = 3;

summe = summe + 15;
summe = summe + 7;
summe = summe + 4;

document.write("<p>Die Summe von 3, 15, 7 und 4 lautet : ");
document.write(summe);
document.write("</p>");
</script>

</body>

Variablen definieren

In diesem Beispiel haben wir unsere Variable summe genannt. Variablennamen sind - unter Einhaltung einiger weniger Regeln, siehe unten - frei wählbar, sollten aber möglichst so gewählt werden, dass man aus dem Namen auf die Verwendung/den Inhalt der Variablen schließen kann.

Wenn wir eine Variable definieren, stellen wir dem Variablennamen das Schlüsselwort var voran - dies zeigt uns und dem Interpreter an, dass hier eine Variablendefinition folgt. Schließlich weisen wir der Variablen noch im Zuge der Definition einen anfänglichen Wert (im Beispiel 3) zu.

Die Zuweisung eines Anfangswerts ist nicht zwingend erforderlich, aber empfehlenswert (außer der Variablen wird kurz nach der Definition ein Anfangswert zugewiesen). Wenn Sie keinen sinnvollen Anfangswert für eine Variable wissen, weisen Sie ihr den symbolischen Wert null zu.

Übrigens: Wenn Sie mehrere Variablen definieren wollen, müssen Sie das var- Schlüsselwort nicht jedes Mal wiederholen. Sie können die zu definierenden Variablen auch durch Kommata getrennt hintereinander auflisten:

var zahl1, zahl2, zahl3;

Werte zuweisen und abfragen

Danach werden dem Wert der Variablen nacheinander die einzelnen Zahlenwerte hinzuaddiert. Eine Zuweisung wie

summe = summe + 15;

bedeutet für den Interpreter, dass er zuerst den Ausdruck auf der rechten Seite des Gleichheitszeichen berechnet und dann das Ergebnis in der Variablen auf der linken Seite speichert. Dabei repräsentiert die Variable summe auf der linken Seite des Gleichheitszeichens den in ihr gespeicherten Wert. Der Interpreter nimmt also den augenblicklich noch in summe gespeicherten Wert 3, addiert zu diesem den Wert 15 und speichert das Ergebnis (18) in summe.

Das Zeichen = steht in JavaScript nicht für einen Vergleich auf Gleichheit, sondern für eine Zuweisung!

Werte von Variablen ausgeben

Zum Schluss wird das Ergebnis der Berechnung ausgegeben. Den Wert einer Variablen gibt man aus, indem man einfach den Variablennamen als Argument an die write- Methode übergibt.

document.write(summe);

Regeln für die Namensgebung

In der Wahl Ihrer Variablennamen (wie auch anderer Bezeichner, beispielsweise Funktionen- oder Klassennamen, siehe nachfolgende Kapitel) sind Sie gänzlich frei, solange Sie sich an folgende Regeln halten:

break

else

new

var

case

finally

return

void

catch

for

switch

while

continue

function

this

with

default

if

throw

delete

in

try

do

instanceof

typeof

Tabelle 9.1: Schlüsselwörter von JavaScript

Außerdem sollten Sie beachten, dass JavaScript streng zwischen Groß- und Kleinschreibung (was bedeutet, dass summe und Summe zwei vollkommen unabhängige Variablen bezeichnen) und dass man Variablennamen möglichst so wählen sollte, dass man aus dem Namen auf die Verwendung/den Inhalt der Variablen schließen kann.

Konstanten

Werte, die man direkt in den Programmcode schreibt (beispielsweise um sie Variablen zuzuweisen), nennt man Konstanten (oder Literale).

var meineZahl, meinString;
meineZahl = 133;
meinString = "Hallo";

Obiger Code verwendet eine Ganzzahlkonstante (133) und eine Stringkonstante ("Hallo").

Text oder Zeichenfolgen in Programmen bezeichnet man gemeinhin als Strings.

Wie eine Konstante aussieht, hängt von ihrem Datentyp ab.

Datentyp

Literale

Beispiele

Null-Wert

null

var = null;

Boolesche Werte

true oder false

var = true;

Zahlen

Dezimalzahlen: 123, -12

Hexadezimalzahlen (beginnen mit 0x)

Fließkommazahlen (Bruchzahlen mit Punkt oder Zahlen in Exponentialschreibweise)

var = 123;
var = 0x10; // gleich 16
var = 3.14;
var = 1.5e3; // gleich 1500

Strings

Zeichenfolgen, die in einfachen oder doppelten Anführungszeichen stehen.

var = 'Hallo';
var = "Hallo";

Tabelle 9.2: Konstanten

Werte für Variablen vom Websurfer abfragen

Programme, die ausschließlich Daten verarbeiten, die vom Programmierer vorgegeben werden, sind meist recht langweilig. Interessanter wird es, wenn ein Programm Daten verarbeitet, die von außen kommen: beispielsweise die Eigenschaften einer Webseite oder Werte, die der Besucher der Webseite eingibt.

Der übliche Weg, Daten vom Websurfer abzufragen, führt über die Einrichtung einer Benutzeroberfläche mit Steuerelementen und Formularen (siehe Kapitel 11). Manchmal kommt man aber auch mit der vordefinierten window-Methode prompt aus.

eingabe = prompt("Aufforderung","Vorgabe");

Als Argumente übergibt man einen Text, in dem man dem Websurfer anzeigt, was für eine Eingabe man vom ihm erwartet, und einen Text, der als Standardeingabe vorgegeben wird (und meist aus einem leeren String "" besteht). Der vom Websurfer eingegebene Wert wird als Ergebnis der prompt-Methode zurückgeliefert und kann in einer Variablen gespeichert werden.

Das nachfolgende Beispiel fordert den Websurfer auf einen DM-Wert einzugeben und rechnet diesen in Euro um. Das Ergebnis der Umrechnung wird danach als HTML-Text ausgegeben.

Listing 9.2: euro.html - Benutzereingaben mit prompt abfragen

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>DM/Euro</title>
</head>

<body>
<h1>Umrechnung von DM in Euro</h1>

<script type="text/javascript">

var dm_wert = null;
var euro_wert = null;

dm_wert = prompt("Geben Sie einen Wert in DM an: ","");

euro_wert = dm_wert / 1.95583;

document.write("<p>");
document.write(dm_wert);
document.write(" DM entsprechen ");
document.write(euro_wert);
document.write(" Euro.</p>");
</script>

</body>
</html>

Abbildung 9.1:  Die prompt-Benutzereingabe

Fallstricke und Vertiefung

Im Grunde ist die Programmierung mit Variablen die Einfachheit selbst. Doch manchmal hakt es auch und ohne tiefere Kenntnisse der mit den Variablen verbundenen Konzepte sind solche Fehler nicht leicht zu finden.

L- und R-Wert

Wie Sie wissen, sind Variablen mit Speicherzellen verbunden. Über den Variablennamen können Sie sowohl einen Wert in einer Variablen abspeichern als auch den Wert einer Variablen abfragen. Woher aber weiß der Interpreter, ob Sie den Wert einer Variablen abfragen oder einen neuen Wert in einer Variablen abspeichern wollen.

Nun, im Grunde ist es recht einfach. Nach der Definition repräsentiert der Variablenname grundsätzlich den Wert der Variablen. Nur wenn der Variablenname auf der linken Seite einer Zuweisung auftaucht, steht er rein für den Speicherplatz, in dem der Ergebniswert des rechten Teils der Zuweisung abzulegen ist.

In einer einzigen Zuweisung kann ein Variablenname also sowohl den Wert der Variablen als auch den Speicherplatz der Variablen repräsentieren:

summe = summe + 15;

Aus diesem Grunde spricht man auch vom L-Wert (Linkswert = Speicher der Variablen, in dem ein neuer Wert abgelegt werden kann) und R-Wert (Rechtswert, aktueller Wert der Variablen).

Implizite Variablendefinition durch Zuweisung

Variablen müssen in JavaScript nicht explizit mit var definiert werden. Jede Zuweisung kann zu einer Variablendefinition werden, wenn Sie auf der linken Seite der Zuweisung einen bisher noch nicht benutzten Variablennamen verwenden.

Statt

<script type="text/javascript">
var summe = null;

summe = 3 * 15;

document.write("<p>");
document.write(summe);
document.write("</p>");
</script>

könnte man also auch schreiben:

<script type="text/javascript">
summe = 3 * 15;

document.write("<p>");
document.write(summe);
document.write("</p>");
</script>

Hey, dann können wir uns ja den ganzen formellen Kram mit der Variablendefinition sparen?! Tja, so war es wohl gedacht. Vermutlich waren die Erfinder von JavaScript der Auffassung, dass man es Webdesignern nicht zumuten kann, ihre Variablen vor dem Gebrauch zu definieren. Nur leider handelt man sich damit viel Ärger ein, denn der Interpreter kann nicht mehr zwischen einem Tippfehler und einer neu zu definierenden Variablen unterscheiden. Schauen wir uns als Beispiel eine Variante des Skriptes aus Listing 9.2 an:

<script type="text/javascript">

var dm_wert = null;
var euro_wert = null;

dm_Wert = prompt("Geben Sie einen Wert in DM an: ","");

euro_wert = dm_wert / 1.95583;

document.write("<p>");
document.write(dm_wert);
document.write(" DM entsprechen ");
document.write(euro_wert);
document.write(" Euro.</p>");
</script>

Wenn dieses Skript ausgeführt wird, lautet die HTML-Ausgabe stets:

null DM entsprechen 0 Euro.

Was ist hier schief gelaufen?

Der Fehler liegt in der Zuweisung der Benutzereingabe an die vermeintliche Variable dm_wert. In der Zuweisung haben wir nämlich aus Versehen das w groß geschrieben:

dm_Wert = prompt("...

Da JavaScript streng zwischen Groß- und Kleinschreibung unterscheidet, bezieht der Interpreter den Bezeichner dm_Wert nicht auf die zuvor definierte Variable dm_wert. Da der neue Bezeichner dm_Wert auf der linken Seite einer Zuweisung auftaucht, erzeugt der Interpreter einfach eine neue Variable für den Bezeichner und weist dieser den Ergebniswert der prompt-Methode zu.

Da wir aber im weiteren Verlauf des Codes wieder auf die eigentliche Variable dm_wert zugreifen, wird der vom Webbesucher eingegebene Wert gar nicht beachtet.

In obigem Beispiel wird der Fehler beim Testen des Skriptes im Browser schnell offensichtlich. Manchmal sind solche Fehler aber nicht so einfach zu erkennen und führen unbemerkt zu falschen Ergebnissen. Man könnte solche Fehler vermeiden, wenn der Interpreter nur Variablen akzeptieren würde, die zuvor explizit deklariert worden sind. Vielleicht wird dies irgendwann in der Zukunft sogar der Fall sein. Bis dahin heißt es aufpassen und gewöhnen Sie sich schon einmal einen sauberen Programmierstil an, indem Sie alle Variablen vorab deklarieren.

Datentypen von Variablen

JavaScript unterscheidet zwischen vier Arten von Daten plus zwei Sondertypen.

Datentyp

Beschreibung

Boolean

Datentyp für Wahrheitswerte. Es gibt nur zwei erlaubte Werte, für die die Schlüsselwörter true (wahr) und false (falsch) definiert sind.

Zahl

Datentyp für Ganz- und Bruchzahlen.

String

Datentyp für Zeichenfolgen (Text)

Objekt

Strukturierter Datentyp für komplexere Daten, siehe 9.5.

Tabelle 9.3: JavaScript-Datentypen

Die Sondertypen umfassen jeweils nur einen Wert.

Wert/Datentyp

Beschreibung

undefined

Variablen, die definiert sind, denen aber noch kein Wert zugewiesen wurde, haben automatisch den Wert undefined.

null

Null-Wert. Programmierer können ihren Variablen diesen Wert zuweisen, wenn Sie anzeigen wollen, dass diese Variable noch keinen vernünftigen Wert enthält. Beispielsweise liefern die JavaScript-Methode prompt den null-Wert zurück, wenn der Webbesucher den Eingabedialog durch Drücken der Abbrechen-Taste schließt. Dank des null-Wertes kann der Programmierer also unterscheiden, ob der Webbesucher den Zahlenwert 0 eingegeben hat, oder ob er den Dialog abgebrochen hat.

Tabelle 9.4: Sondertypen

Da JavaScript eine nur »schwach typisierte« Programmiersprache ist, können Sie einer Variablen Werte jedes dieser Datentypen zuweisen, ja Sie können ein und derselben Variablen sogar nacheinander Werte verschiedener Datentypen zuweisen.

var meineVar = null;
meineVar = -123;
meineVar = "Hallo";

Leser, die von der C/C++- oder Java-Programmierung herkommen, wird hierbei das kalte Grausen erfassen, denn solcher Typenmischmasch ist in diesen Sprachen (aus guten Gründen) nicht erlaubt. Und auch wir als JavaScript-Programmierer sollten uns darum bemühen, unsere Variablen möglichst sauber nach Datentypen zu trennen. Das heißt, wenn wir eine Variable alter definiert haben, in der wir das vom Webbesucher eingegebene Alter abspeichern (also eine Zahl), sollten wir nicht weiter unten im Skript darauf verfallen, in der Variablen einen auszugebenden Text zwischenzuspeichern (selbst dann nicht, wenn die Altersangabe nicht mehr benötigt wird).

Jeder Variable kommt im Skript eine bestimmte Bedeutung zu. Vermeiden Sie es, Bedeutung oder Datentyp einer Variable im Verlaufe eines Skriptes zu ändern. Definieren Sie lieber eine weitere Variable.

Typenumwandlung

Manchmal ist es aber erforderlich, den Typ einer Variablen (oder eines Wertes) umzuwandeln. Betrachten wir dazu noch einmal den Code aus unserem Euro-Skript:

var dm_wert   = null;
var euro_wert = null;

dm_wert = prompt("Geben Sie einen Wert in DM an: ","");

euro_wert = dm_wert / 1.95583;

...
document.write(euro_wert);
...

Zu Beginn des Codes werden zwei Variablen dm_wert und euro_wert definiert und mit null initialisiert. Die Variablen gehören danach dem Sondertyp null an.

Dann wird vom Besucher der Webseite ein Zahlenwert abgefragt und in der Variablen dm_wert gespeichert. Benutzereingaben sind immer Strings, und folglich liefert die prompt- Methode auch einen String zurück. Wenn der Webbesucher beispielsweise 123 eingibt, liefert prompt nicht den Zahlenwert 123, sondern den String "123" zurück! Dieser String wird nun in dm_wert gespeichert. Der Typ der Variablen dm_wert ändert sich also vom Null- Typ in den String-Typ. Da der Null-Typ ein Sondertyp ist, ist dies nicht weiter aufregend. Richtig gefährlich wird es aber in der nächsten Zeile.

euro_wert = dm_wert / 1.95583;

Hier soll der Wert von dm_wert durch 1.95583 dividiert werden. dm_wert enthält aber einen String. Wie bitte kann man einen String (also einen Text) durch eine Zahl teilen? Hier schreitet der Interpreter ein. Er erkennt, dass eine Division durchzuführen ist, und da er weiß, dass man nur Zahlen dividieren kann, versucht er den String in eine Zahl umzuwandeln. Enthält der String tatsächlich eine brauchbare Zahlenangabe, so ist dies kein Problem. Und so wird aus dem String "123" die Zahl 123.

Diese Umwandlung gilt nur für den Wert im Ausdruck, das heißt, im Ausdruck steht dm_wert jetzt für die Zahl 123, in der Variablen dm_wert ist aber weiter der String "123" gespeichert.

Das Ergebnis der Division wird in der Variablen euro_wert abgespeichert, die danach dem Zahlen-Typ angehört.

Zum Schluss wird die Variable euro_wert ausgegeben. Ausgaben sind aber immer Strings, und so wandelt der Interpreter für die Ausgabe mit write den Wert von euro_wert in einen String um.

Binärcodierung von Daten

Sie sehen: die Realität ist wieder einmal viel komplizierter als es auf den ersten Blick erscheint. Der Grund hierfür ist, dass im Computer alle Daten als Bitfolgen gespeichert werden müssen (Bitfolgen sind Folgen von 0 und 1, was im Computer meist elektrische Spannung oder keine elektrische Spannung bedeutet).

Dabei verwendet der Computer für die einzelnen Datentypen unterschiedliche Codierungsverfahren. Aus diesem Grunde sieht die Bitfolge, die einen Zahlenwert 123 repräsentiert, ganz anders aus als die Bitfolge, die den String »123« repräsentiert. Während wir Menschen einen String »123« ohne Probleme auch als Zahl 123 interpretieren können1, muss der JavaScript-Interpreter dazu erst die Bitfolgen ineinander umwandeln.

Glücklicherweise haben wir mit diesen Interna bei der Programmierung wenig zu tun, da der Interpreter die Daten bei Bedarf automatisch konvertiert (siehe oben).

Was aber, wenn der Interpreter nicht so konvertiert, wie wir es uns vorstellen? Nehmen wir zum Beispiel die Addition mit dem Plus-Operator. Im Gegensatz zur Division, die nur für Zahlen erlaubt ist, gilt die Addition für Zahlen und Strings2. Was also passiert, wenn wir eine Zahl und einen String addieren?

var zahl1 = 111;
var zahl2 = null;
var summe = null;

zahl2 = prompt("Geben Sie eine Zahl ein: ","");

summe = zahl1 + zahl2;

document.write(summe);

Beachten Sie, dass die Variable zahl2 einen String-Wert enthält. (Nur weil wir die Variable hoffnungsfroh zahl2 getauft haben, wird der Interpreter nicht dafür sorgen, dass diese Variable nur Zahlenwerte aufnimmt. Entscheidend ist hier, dass prompt einen String zurückliefert, der in zahl2 gespeichert wird. Für die weitere Besprechung des Beispiels nehmen wir einfach an, der Webbesucher hat 222 eingegeben und in zahl2 steht jetzt der String "222".

Bei der Addition trifft der Interpreter nun auf eine Zahl (zahl1) und einen String (zahl2). Was wird er tun? Wenn Sie das Beispiel nachprogrammieren, werden Sie feststellen, dass der Interpreter zahl1 in einen String umwandelt, denn die Ausgabe dieses Codes lautet:

111222

Das ist sicherlich nicht das, was wir mit unserem Skript erreichen wollten. Wie kann man den Interpreter also dazu bringen, zahl2 in eine Zahl zu konvertieren?

Wenn der Interpreter die Werte von Variablen nicht so konvertiert, wie Sie es möchten, müssen Sie selbst für die richtige Konvertierung sorgen. Für die Konvertierung eines Strings in eine Zahl stellt uns JavaScript zwei window-Methoden zur Verfügung.

Funktion

Beschreibung

parseInt(string, basis)

Überprüft, ob der erste Teil eines Strings einen Integer enthält. Im zweiten Parameter wird die Basis des Zahlensystems angegeben. Wird keine Basis angegeben, liefert die Funktion eine Dezimalzahl zurück.

a=parseInt("4 Kinder") liefert a = 4

parseFloat(string)

Entspricht in etwa parseInt(), sucht jedoch nach Fließkommazahlen.

a="1.7 Kinder im Durchschnitt" liefert a = 1.7

Tabelle 9.5: Konvertierungsfunktionen

Damit die Addition wie gewünscht ausgeführt wird, müssen wir also schreiben:

summe = zahl1 + parseFloat(zahl2);

Gültigkeitsbereiche

Variablen kann man an beliebiger Stelle im Skriptcode definieren. Trotzdem ist es nicht ganz unerheblich, wo man eine Variable definiert, denn der Ort der Definition legt auch den Gültigkeitsbereich der Variable (im Englischen »scope«) fest.

Eine Variable kann entweder lokal, d.h. innerhalb einer Funktion, oder global, d.h. außerhalb einer Funktion deklariert werden. Lokale Variablen sind nur innerhalb der Funktion gültig, in der Sie definiert wurden. Globale Variablen sind ab dem Ort Ihrer Deklaration im aktuellen und allen nachfolgenden <script>-Tags gültig.

Im ersten Moment könnte man meinen, globale Variablen sind ein praktisches Mittel, um vorab am Anfang der Webseite einen Schwung passender globaler Variablen zu definieren, die man dann weiter unten in dem einen oder anderen <script>-Element oder der einen oder anderen JavaScript-Funktion verwendet. Doch dieser Missbrauch globaler Variablen führt zu nur schwer verständlichem Code und öffnet Bugs (liebevolle Bezeichnung für Programmierfehler) Tür und Tor. Versuchen Sie stattdessen Ihren Code so modular wie möglich zu halten, indem Sie für jede Funktion und jedes <script>-Element eigene Variablen definieren. Nur wenn Sie von mehreren <script>-Elementen oder JavaScript- Funktionen auf ein und dieselbe Variable zugreifen wollen, sollten Sie diese als globale Variable zugänglich machen.

Verdeckung und Überschreibung

Wenn Sie in einer Funktion eine lokale Funktion definieren, die den gleichen Namen wie eine zuvor definierte globale Variable trägt, verdeckt die lokale Variable in der Funktion die globale Variable. Das bedeutet, dass sich der Bezeichner innerhalb der Funktion immer auf die lokale Funktion bezieht, während außerhalb weiter die globale Variable verfügbar ist.

Listing 9.3: Auszug aus scope.html

<body>
<h1>Verdeckung</h1>

<script type="text/javascript">
var meineVariable = 3; // globale Variable

document.write("<p>Wert von meinVariable in 1. Skriptelement: ");
document.write(meineVariable); // Ausgabe: 3
document.write("</p>");
</script>

<script type="text/javascript">
function funk()
{
var meineVariable = 5; // lokale Variable
// verdeckt globale Variable

document.write("<p>Wert von meinVariable in Funktion: ");
document.write(meineVariable); // Ausgabe: 5
document.write("</p>");
}

funk();

document.write("<p>Wert von meinVariable in 2. Skriptelement: ");
document.write(meineVariable); // 3 (alte globale Variable)
document.write("</p>");
</script>

</body>

Wenn Sie dagegen in einem <script>-Element eine globale Variable definieren, die den gleichen Namen wie eine bereits zuvor definierte globale Variable trägt, überschreibt die später definierte globale Variable die zuvor definierte globale Variable. Der globale Bezeichner bezieht sich also auf die zuletzt definierte globale Variable.

9.2 Operatoren und Ausdrücke

Wie man Daten in Variablen zwischenspeichert, wissen wir jetzt. Der nächste Schritt ist, mit den Daten zu arbeiten, sie auszuwerten, sie zu verändern. Dies geschieht mit Hilfe von Operatoren. Einige Operatoren haben Sie bereits kennen gelernt, etwa den Zuweisungsoperator = oder den Additionsoperator +. Aber es gibt noch eine ganze Reihe weiterer Operatoren.

Arithmetische Operatoren

Operatoren

Funktion

Beispiel

+

Addition

Verknüpfung von Strings

3 + 4

"Hallo" + "Joe"

-

Subtraktion

Negation eines Wertes

3 - 4

-12

*

Multiplikation

3 * 4

/

Division

3 / 4

%

Modulo

4 / 3

++

Inkrement

++var

var++

--

Dekrement

--var

var--

Tabelle 9.6: Arithmetische Operatoren

Die arithmetischen Operatoren dienen vor allem der Bearbeitung von Zahlen und werden so eingesetzt, wie man es aus der algebraischen Mathematik kennt (einzige Ausnahme ist der +-Operator, mit dem man Strings aneinander hängen kann). Das folgende Skript fragt zum Beispiel vom Besucher der Webseite zwei Zahlenwerte ab und multipliziert diese mit Hilfe des *-Operators.

Da der *-Operator im Gegensatz zum +-Operator nicht für Strings definiert ist, können wir uns die explizite Typumwandlung der Eingaben sparen (siehe vorangehender Abschnitt zu Typumwandlung).

Listing 9.4: multiplizieren.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Operatoren</title>
</head>

<body>
<h1>Multiplikation</h1>

<script type="text/javascript">

var zahl1 = prompt("Geben Sie eine Zahl ein: ","");
var zahl2 = prompt("Geben Sie eine Zahl ein: ","");

var produkt = zahl1 * zahl2;

document.write("<p>");
document.write(zahl1);
document.write(" * ");
document.write(zahl2);
document.write(" ist gleich ");
document.write(produkt);
document.write("</p>");
</script>

</body>
</html>

Womöglich nicht ganz so bekannt wie die Multiplikation oder Addition sind Modulo, Inkrement und Dekrement.

Modulo

Der Modulo-Operator teilt seinen ersten Operanden ganzzahlig durch den zweiten Operanden und gibt den dabei verbleibenden Rest zurück.

Wenn Sie beispielsweise schreiben:

var zahl1 = 8;
var zahl2 = 3;

var produkt = zahl1 % zahl2;

wird in der Variablen produkt der Wert 2 abgespeichert. Der Interpreter teilt 8 durch 3 und stellt fest, dass bei einer Ganzzahldivision ein Rest von 2 bleibt. Diesen Wert liefert er als Ergebnis der Modulo-Operation zurück.

Der Modulo-Operator kann in JavaScript auch zusammen mit Bruchzahlen verwendet werden.

Inkrement und Dekrement

Eine bei der Programmierung häufig benötigte Operation ist das Erhöhen oder Vermindern des Werts einer Variablen um 1.3 Man bezeichnet dies als Inkrement (Erhöhung um 1) oder Dekrement (Verminderung um 1).

Damit man zur Inkrementierung einer Variablen nicht immer

var = var + 1;

schreiben muss, gibt es in JavaScript den Inkrementoperator:

++var;

Entsprechend schreibt man zur Dekrementierung einer Variablen:

--var;

Inkrement- und Dekrementoperator kann man der Variablen voranstellen (Präfixnotation: ++var) oder nachstellen (Postfixnotation: var++).

Wenn man die Operatoren alleine in einer Anweisung benutzt

++var;
var++;

spielt es keine große Rolle, welche Version man verwendet.

Geschwindigkeitsfanatiker wird es interessieren, dass die Präfixnotation schneller ist, da der Interpreter für ihre Implementierung weniger Maschinenbefehle benötigt.

Wenn Sie die Operatoren aber in einem Ausdruck - beispielsweise auf der rechten Seite einer Zuweisung - verwenden, stellt sich die Frage, welcher Wert des Operanden für die Berechnung des Ausdrucks verwendet wird. Schauen Sie sich dazu die folgende Anweisung an:

var zahl1 = 12;
zahl2 = 4 * ++zahl1;

Welchen Wert hat zahl2 nach Ausführung dieses Codes? Um diese Frage zu beantworten, muss man wissen, welchen Wert ++zahl1 in dem Ausdruck repräsentiert: den Wert, den zahl1 vor der Inkrementierung hat, oder den Wert, den die Variable nach der Inkrementierung hat?

Zuweisungsoperatoren

Mit dem Zuweisungsoperator kann man in einer Variablen den Ergebniswert eines Ausdrucks abspeichern:

zahl1 = 3;
zahl1 = 3 + 4;
zahl2 = zahl1 * (3 + zahl1);
zahl2 = zahl2 + 4;

Wir haben in unseren Skripten bereits fleißig von ihm Gebrauch gemacht.

Was wir Ihnen bisher verschwiegen haben, ist, dass es Kurzfassungen für Operationen gibt, in denen der neue Wert der Variable auf ihrem alten Wert basiert. Solche Operationen haben wir bisher immer so formuliert, dass wir die Variable auf der linken und rechten Seite des Zuweisungsoperators verwendet haben:

zahl2 = zahl2 + 4;      // Erhöht den Wert von zahl2 um 4
zahl2 = zahl2 * 4; // Multipliziert den Wert von zahl2 mit 4

Kürzer kann man diese Operationen mit Hilfe eines zusammengesetzten Zuweisungsoperators schreiben:

zahl2 += 4;
zahl2 *= 4;

Kombinierte Zuweisungsoperatoren gibt es für die arithmetischen Operationen:

+=, -=, *=, /=, %=

und die Bitoperatoren (siehe Abschnitt 9.2.4):

|=, ^=, &=, <<=, >>= und >>>=

Die kombinierten Zuweisungsoperationen sparen nicht nur Tipparbeit, meist werden sie auch schneller ausgeführt.

Vergleiche und logische Operatoren

Die letzte wirklich wichtige Gruppe von Operatoren sind die Vergleichsoperatoren. Das Vergleichen von Werten spielt in der Programmierung eine ganz besondere Rolle, denn auf der Grundlage solcher Vergleiche kann man den Ablauf eines Programms steuern. Wie dies geht werden Sie in Abschnitt 9.3 erfahren. Die zugehörigen Vergleichsoperatoren sollen Sie jetzt schon kennen lernen.

Vergleichsoperatoren

Operatoren

Funktion

Beispiel

==

Gleichheit

Liefert true, wenn beide Werte gleich sind.

var1 == var2

!=

Ungleichheit

Liefert true, wenn beide Werte ungleich sind.

var1 != var2

<

Kleiner

Liefert true, wenn der erste Wert kleiner ist als der zweite

var1 < var2

<=

Kleiner gleich

Liefert true, wenn der erste Wert kleiner oder gleich dem zweiten ist

var1 <= var2

>

Größer

Liefert true, wenn der erste Wert größer ist als der zweite

var1 > var2

>=

Größer gleich

Liefert true, wenn der erste Wert größer oder gleich dem zweiten ist

var1 >= var2

Tabelle 9.7: Vergleichsoperatoren

Allen Vergleichsoperatoren gemein ist, dass Sie sowohl für Boolesche Werte, Zahlen oder auch Strings verwendet werden können und als Ergebnis einen Booleschen Wert zurückliefern (true oder false), je nachdem, ob die Behauptung des Vergleichs wahr oder falsch ist.

Wie werden Strings verglichen?

Strings werden lexikographisch verglichen, das heißt, der Interpreter geht die Strings parallel Zeichen für Zeichen von vorne nach hinten durch, bis sich die Strings in einem Zeichen unterscheiden. Dann prüft er, welches Zeichen im Alphabet früher kommt. Der String mit diesem Zeichen ist dann kleiner als der andere String.

Genau genommen prüft der Interpreter nicht nach der Reihenfolge im Alphabet, sondern nach der Reihenfolge der Zeichen in der Unicode-Tabelle.

Kompliziert kann es werden, wenn eine Zahl mit einem String verglichen wird. In solchen Fällen kann man einen arithmetischen Zahlenvergleich beziehungsweise einen lexikographischen Stringvergleich erzwingen, indem man die zu vergleichenden Werte mit Hilfe eines Tricks entsprechend umwandelt:

("" + var1) == (""+ var2)         // erzwingt einen Stringvergleich
(var1 - 0) == (var2 - 0) // erzwingt einen Zahlenvergleich

JavaScript kennt laut ECMA noch zwei weitere Vergleichsoperatoren: === und !==. === liefert false, wenn die beiden verglichenen Werte unterschiedlichen Datentypen angehören, !== liefert in so einem Fall entsprechend true.

Logische Operatoren

Mit Hilfe der folgenden Operatoren kann man die Ergebnisse von Vergleichen kombinieren oder umwandeln.

Operatoren

Funktion

Beispiel

!

Logisches NICHT

Wandelt den Ergebniswert eines Vergleichs um. Liefert der Vergleich also beispielsweise true, macht der !-Operator daraus false.

!(var1 == var2)

&&

Logisches UND

Liefert true, wenn beide kombinierten Vergleiche true liefern.

(var1 < var2) && (var3 > var2)

||

Logisches ODER

Liefert true, wenn mindestens einer der beiden kombinierten Vergleiche true liefert.

(var1 < var2) || (var3 > var2)

Tabelle 9.8: Vergleichsoperatoren

Bitweise Operatoren

Mit Hilfe der Operatoren &, |, ^, <<, >> und >>> kann man Werte auf Bitebene manipulieren. Diese Operatoren sollten erfahrenen Programmierern vorbehalten bleiben, weswegen wir auf diese Operatoren, die im Übrigen ganz wie in anderen Programmiersprachen verwendet werden, nicht näher eingehen werden.

Ausdrücke und Anweisungen

Eine Kombination aus Werten, Variablen und Operatoren, die vom Interpreter zu einem Ergebniswert berechnet werden kann, bezeichnen Programmierer als Ausdruck.

Gültige Ausdrücke sind beispielsweise:

var1
var1 * 3
3 < var2
1 + 2 + 3 + var1 * var2

Ausdrücke findet man beispielsweise auf der rechten Seite von Zuweisungen, in Bedingungen von Verzweigungen und Schleifen (siehe Abschnitt 9.3) oder als Argumente in Funktionsaufrufen (siehe Abschnitt 9.4.2).

Da in einem Ausdruck mehrere Operatoren vorkommen können, ist es wichtig zu wissen, in welcher Reihenfolge die Operatoren abgearbeitet werden. Die folgende Aufzählung beginnt mit den vorrangig ausgeführten Operationen und geht bis zu der stets zuletzt ausgeführten Zuweisung.

Gefällt Ihnen diese Reihenfolge nicht, können Sie sie durch das Setzen von Klammern verändern.

Machen wir einen kleinen Test. Wie sieht zum Beispiel das Ergebnis folgender Berechnung aus?

var zahl1 = 3;
var zahl2 = 2;
var zahl3 = 7;

var ergebnis = zahl1 + zahl2 * zahl3;

Es lautet 17, weil die Multiplikation von zahl2 * zahl3 vor der Addition ausgeführt wird. Wenn Sie möchten, dass zuerst die Addition ausgeführt und das Ergebnis dann mit zahl3 multipliziert wird, müssen Sie schreiben:

var zahl1 = 3;
var zahl2 = 2;
var zahl3 = 7;

var ergebnis = (zahl1 + zahl2) * zahl3;

Schon lautet das Ergebnis 35.

Anweisungen

Ein Ausdruck ist letztendlich nicht mehr als Wert, den der Interpreter nach einer mehr oder weniger komplizierten Formel berechnet. Ein Ausdruck ist aber noch kein Befehl an den Computer. Befehle bezeichnet man in der Programmiersprache als Anweisungen und man erkennt sie daran, dass sie stets mit einem Semikolon ; abgeschlossen werden. Einige Anweisungen haben Sie bereits kennen gelernt,

beispielsweise die Variablendeklaration:

var meineZahl1, meineZahl2;

oder die Zuweisung:

meineZahl1 = 3 * meineZahl2;

Anweisungen können mittels geschweifter Klammern zu Blöcken zusammengefasst werden. Wir kennen dies bereits aus der Funktionsdefinition, wo alle Anweisungen, die zu der Funktion gehören, in geschweiften Klammern stehen:

function fkt_name()
{
document.bgColor = "cyan";
}

9.3 Steuerung des Programmablaufs

Anweisungen werden standardmäßig nacheinander von oben nach unten abgearbeitet und ausgeführt. Meist ist dies auch genau das, was wir wollen. Manchmal jedoch würde man sich etwas mehr Flexibilität wünschen, beispielsweise wenn man in Abhängigkeit von dem Wert einer Variablen verschiedene Anweisungen ausführen lassen möchte oder wenn man eine bestimmte Anweisung mehrere Male hintereinander ausführen lassen möchte.

Für solche Aufgaben stellt JavaScript verschiedene Kontrollstrukturen zur Verfügung, mit denen man den Programmablauf steuern kann.

Technisch gesehen zählen diese Kontrollstrukturen auch zu den Anweisungen, auch wenn sie meist nicht direkt mit einem Semikolon abgeschlossen werden.

Die if-Verzweigung

Die if-Verzweigung entscheidet, ob ein nachfolgender Anweisungsblock ausgeführt werden soll oder nicht. Dazu wird - meist mit Hilfe der Vergleichsoperatoren (siehe Abschnitt 9.2.3) - eine Bedingung formuliert, die vom Programm zur Laufzeit ausgewertet wird. Ist die Bedingung erfüllt (true), wird der auf die Bedingung folgende Block ausgeführt, ist die Bedingung falsch (false), wird der Block übersprungen und das Programm wird mit der nächsten Anweisung hinter der if-Verzweigung fortgeführt.

Die allgemeine Syntax der if-Bedingung sieht wie folgt aus:

if (Bedingung)
{
Anweisung(en);
}

Diese Konstruktion kann man wie einen deutschen Konditionalsatz lesen:

»Wenn die Bedingung erfüllt ist, dann (und nur dann) führe die Anweisungen aus«

Wenn Sie beispielsweise die Wurzeln von Zahlen berechnen, müssen Sie beachten, dass die Wurzel nur für positive Zahlen definiert ist.

Listing 9.5: if.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>if-Verzweigung</title>
</head>

<body>
<h1>Wurzelberechnung</h1>

<script type="text/javascript">

var eingabe;
var wurzel;

eingabe = prompt("Von welchem Wert wollen Sie die Wurzel berechnen: ",
"");

if (eingabe >= 0)
{
wurzel = Math.sqrt(eingabe);

document.write("<p>Die Wurzel von ");
document.write(eingabe);
document.write(" ist ");
document.write(wurzel);
document.write(".</p>");
}

</script>

</body>
</html>

Abbildung 9.2:  Ausgabe des Codes aus if.html

Da die Verwendung der if-Verzweigung nicht schwer zu verstehen ist, möchte ich Ihre Aufmerksamkeit hier auf die Berechnung der Wurzel lenken. Viele mathematische Funktionen, die uns allen so geläufig sind, dass man verleitet ist, sie als »einfache« Operationen anzusehen (beispielsweise der Sinus oder die Wurzel), sind in Wirklichkeit nur schwierig und mit Hilfe komplizierter mathematischer Algorithmen zu berechnen. Da es keinem Programmierer zuzumuten ist, diese Algorithmen selbst zu implementieren, legt der ECMA-Standard fest, dass jeder JavaScript-Interpreter ein7 Math-Objekt zu Verfügung stellen soll, das die wichtigsten mathematischen Funktionen als Methoden implementiert. So heißt die Methode für die Berechnung der Wurzel beispielsweise sqrt() (steht für »square root«) und liefert als Ergebnis die Wurzel des übergebenen Arguments zurück.

wurzel = Math.sqrt(eingabe);

Soll die if-Bedingung nur eine einzige Anweisung kontrollieren, brauchen Sie diese nicht in geschweifte Klammern einzuschließen.

Schließen Sie die if-Bedingung nie, wirklich nie, mit einem Semikolon ab!!! Der Interpreter denkt dann, dass das Semikolon für eine leere Anweisung (eine Anweisung, die nichts macht) stehe und dass die if-Bedingung diese leere Anweisung kontrolliere.

Die else-Alternative

Mit einer if-else-Konstruktion kann man in Abhängigkeit von einer Bedingung den einen oder den anderen Block ausführen lassen. Wir wollen uns dies in unserem Wurzel- Programm zunutze machen, indem wir den Anwender im Falle negativer Eingaben gezielt auf seinen Fehler hinweisen.

Listing 9.6: Auszug aus else.html

<script type="text/javascript">
var eingabe;
var wurzel;

eingabe = prompt("Von welchem Wert wollen Sie die Wurzel berechnen: ",
¬"");

if (eingabe >= 0)
{
wurzel = Math.sqrt(eingabe);

document.write("<p>Die Wurzel von ");
document.write(eingabe);
document.write(" ist ");
document.write(wurzel);
document.write(".</p>");
}
else
{
document.write("<p>Sie haben die Zahl ");
document.write(eingabe);
document.write(" eingegeben.</p>");
document.write("<p>Die Wurzel kann aber nur für positive Zahlen /
¬berechnet werden.</p>");
}

</script>

Abbildung 9.3:  Ausgabe von else.html

Soll der else-Teil nur eine einzige Anweisung kontrollieren, brauchen Sie diese nicht in geschweifte Klammern einzuschließen.

Die switch-Verzweigung

Will man die Programmausführung in Abhängigkeit vom Wert einer Variablen mehrfach aufspalten, bietet sich dazu eine switch-Konstruktion an.

switch(variable)
{
case Wert1: Anweisung(en); break;
case Wert2: Anweisung(en); break;
case Wert3: Anweisung(en); break;
case Wert4: Anweisung(en); break;
default: Anweisung(en);
}

Die switch-Anweisung vergleicht den Wert in der Variablen mit den Werten der case- Marken. Wird eine Übereinstimmung gefunden, springt die Programmausführung zur ersten Anweisung neben der case-Marke. Von dort ab, werden alle nachfolgenden Anweisungen in der switch-Verzweigung ausgeführt. Will man verhindern, dass der Code nachfolgender case-Marken ebenfalls ausgeführt wird, muss man die Anweisungsfolgen der case-Marken mit einer break-Anweisung abschließen. Diese sorgt dafür, dass die Programmausführung zum Ende der switch-Verzweigung springt.

Wird keine Übereinstimmung gefunden, springt die Programmausführung in den default- Block (sofern ein solcher aufgesetzt wurde).

Listing 9.7: switch.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>switch-Verzweigung</title>
</head>

<body>
<script type="text/javascript">

var alter;

alter = prompt("In welche Altersklasse fallen Sie? \n \
1 (5-18), 2 (19-65) oder 3 (66-100)","");

switch(parseInt(alter))
{
case 1: document.bgColor = "pink";
document.write("<h1>Hi, willkommen auf meiner
¬Website</h1>");
break;
case 2: document.bgColor = "cyan";
document.write("<h1>Hallo und willkommen auf meiner
¬Website</h1>");
break;
case 3: document.bgColor = "white";
document.write("<h1>Willkommen auf meiner Website</h1>");
break;
default: document.bgColor = "white";
document.write("<h1>Willkommen auf meiner Website</h1>");
break;
}

</script>

</body>
</html>

Abbildung 9.4:  Ausgabe nach Eingabe von 1

Mit Hilfe der switch-Anweisung kann die Programmausführung sehr gut in Abhängigkeit von den verschiedenen Werten einer Variablen aufgespalten werden. Sie unterliegt aber auch gewissen Beschränkungen:

An sich ist die Programmierung mit der switch-Verzweigung nicht sonderlich kompliziert, es gibt aber zwei Fallstricke, über die man als Anfänger leicht stolpern kann:

Passen Sie auf, von welchem Typ die Variable in der switch-Bedingung ist, und formulieren Sie entsprechend die case-Marken.

Die for-Schleife

Schleifen dienen dazu einen Anweisungsblock mehrfach hintereinander auszuführen. Eine der am häufigsten verwendeten Schleifen ist die for-Schleife.

for (Initialisierung; Bedingung; Veränderung)
{
Anweisung(en);
}

Wie im Falle der if-Bedingung gilt: Kein Semikolon hinter dem Schleifenkopf!

Mit Hilfe einer solchen Schleife kann man beispielsweise bequem die ersten zehn Quadratzahlen berechnen und ausgeben.

Listing 9.8: for.html - Anweisungen mehrfach ausführen lassen

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>for-Schleife</title>
</head>

<body>
<h1>Die Quadratzahlen</h1>

<script type="text/javascript">

var quadrat;
var loop;

for (loop=1; loop <= 10; ++loop)
{
quadrat = loop * loop;

document.write("<p>Das Quadrat von ");
document.write(loop);
document.write(" ist ");
document.write(quadrat);
document.write(".</p>");
}

</script>

</body>
</html>

Abbildung 9.5:  Ausgabe der JavaScript-Schleife

Die Schleife beginnt in der Zeile:

for (loop=1; loop <= 10; ++loop)

Eingeleitet wird die Schleife durch das Schlüsselwort for. In der nachfolgenden Klammer wird festgelegt, wie oft die Schleife durchlaufen wird. Dazu bedarf es einer Schleifenvariablen, die hier »loop« genannt wurde. Bei Eintritt in die Schleife muss der Schleifenvariablen ein Anfangswert zugewiesen werden. Dies geschieht in der Anweisung:

loop = 1;

Dahinter ist die Bedingung formuliert, die festlegt, wie lange die Schleife ausgeführt wird:

loop <= 10;

Solange die Bedingung erfüllt ist, das heißt, solange die Schleifenvariable loop kleiner oder gleich 10 ist, wird die Schleife ausgeführt.

Die dritte Anweisung wird nach jeder Abarbeitung des Schleifenkörpers ausgeführt. Sie zählt die Schleifenvariable hoch, so dass irgendwann die Schleifenbedingung nicht mehr erfüllt ist und die Schleife verlassen werden kann.

Der Schleifenkörper ist durch die geschweiften Klammern markiert.

Ausführung von Schleifen

Beim ersten Schleifendurchgang hat die Schleifenvariable loop noch den Anfangswert 1. Folglich bekommt quadrat den Wert 1 * 1 = 1 zugewiesen. Das Ergebnis wird mit Hilfe der nachfolgenden write-Aufrufe ausgegeben.

Nach Abarbeitung der Anweisungen im Schleifenkörper wird die dritte Anweisung des Schleifenkopfes ausgeführt.

++loop

Bitte beachten Sie, dass die letzte Anweisung im Schleifenkopf nicht mit einem Semikolon abgeschlossen wird.

Danach springt das Programm zurück an den Schleifenanfang. Die Zuweisung

loop = 1;

wird nun nicht mehr ausgeführt, wohl aber die Überprüfung der Bedingung. Da nach jedem Schleifendurchgang die Variable loop um 1 erhöht wird, wird loop nach dem zehnten Durchgang den Wert 11 haben. Die Überprüfung der Bedingung ergibt, dass loop nun größer als 10 ist, und die Schleife wird verlassen.

Fallstricke

Wichtig ist, dass die Schleife auch wirklich wieder verlassen wird. Betrachten Sie folgende Schleife:

for(loop=1; loop <= 10; --loop)
{
...
}

Hier wird die Schleifenvariable loop nach jedem Schleifendurchgang dekrementiert, das heißt, um 1 vermindert. Der Wert von loop wird nie größer als 10 werden, und die Schleife wird nie verlassen!

Solche Endlosschleifen sind ein häufiges Beispiel für logische Fehler innerhalb eines syntaktisch korrekten Programms.

Die while-Schleife

Eine weitere wichtige Schleife ist die while-Schleife. Die while-Schleife wird solange wiederholt ausgeführt, wie die Bedingung neben dem Schlüsselwort while erfüllt ist.

Initialisierung;
while(Bedingung)
{
Anweisung(en); // inklusive Veränderung
}

Ein mögliches Einsatzgebiet für die while-Schleife ist die Abfrage von Benutzereingaben, die einem bestimmten Wertebereich angehören müssen. Durch die while-Schleife kann man die Eingabe so lange wiederholen lassen, bis der Anwender einen korrekten Wert eingibt. In dem folgenden Programm, das eine Abwandlung des Wurzelprogramms aus Listing 9.5 ist, machen wir uns dies zunutze.

Listing 9.9: while.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>while-Schleife</title>
</head>

<body>
<h1>Wurzelberechnung</h1>

<script type="text/javascript">

var eingabe = -1;
var wurzel;

while (eingabe < 0)
{
eingabe = prompt("Von welchem Wert wollen Sie die
¬Wurzel berechnen: ","");
}

wurzel = Math.sqrt(eingabe);

document.write("<p>Die Wurzel von ");
document.write(eingabe);
document.write(" ist ");
document.write(wurzel);
document.write(".</p>");

</script>

</body>
</html>

Die while-Schleife ist flexibler als die for-Schleife, aber auch gefährlicher, denn im Vergleich zur for-Schleife, wo alle Anweisungen, die die Schleifenausführung steuern, im Schleifenkopf zusammengefasst sind (Initialisierung, Prüfung und Veränderung der Schleifenvariable), sind diese Anweisungen bei der while-Schleife mehr oder weniger verstreut und der Interpreter merkt auch nicht, wenn der Programmierer den einen oder anderen Teil vergessen hat. Sie sollten bei Verwendung einer while-Schleife sorgfältig prüfen, ob diese ordnungsgemäß betreten und irgendwann auch wieder verlassen wird. Wir wollen dies einmal an obigem Listing durch exerzieren.

Nehmen wir an, das Skript wird gerade gestartet und der Interpreter trifft auf die while- Schleife.

while (eingabe < 0)

Beim ersten Mal soll der Interpreter auf jeden Fall die Schleife ausführen, damit der Besucher zur Eingabe einer Zahl aufgefordert wird. Der Interpreter führt die Schleife aber nur dann aus, wenn die Variable eingabe einen Wert kleiner Null enthält. Ist dies der Fall? Glücklicherweise ja, denn genau aus diesem Grunde haben wir die Variable eingabe weiter oben mit dem Wert -1 initialisiert.

var eingabe = -1;

Der Interpreter führt jetzt den Code in der Schleife aus, das heißt, der Besucher wird aufgefordert eine Zahl einzugeben und diese wird in der Variablen eingabe abgespeichert. Danach ist der Schleifenkörper das erste Mal komplett abgearbeitet und die Programmausführung springt zurück zur Schleifenbedingung. Angenommen der Besucher hat einen negativen Wert eingegeben. Dann ist die Schleifenbedingung immer noch erfüllt und der Schleifenkörper wird erneut ausgeführt. So wird der Besucher wieder und wieder aufgefordert einen Wert einzugeben, bis er einen positiven Wert eintippt. Dann ist die Schleifenbedingung nicht mehr erfüllt, die Schleife wird nicht mehr ausgeführt und die Programmausführung wird mit der Berechnung der Wurzel fortgesetzt.

Abbruchbedingungen für Schleifen

Die Ausführung einer Schleife kann nicht nur durch das fein abgestimmte Spiel von Schleifenvariable und Schleifenbedingung, sondern auch mit Hilfe spezieller Anweisungen beeinflusst werden.

Anweisung

Beschreibung

continue

Bricht den aktuellen Schleifendurchgang ab und beginnt direkt mit dem nächsten Schleifendurchgang.

break

Bricht eine Schleife mitten in der Ausführung ab und fährt mit der nächsten Anweisung hinter der Schleife fort.

Tabelle 9.9: Abbruchanweisungen für Schleifen

Weitere Schleifen

Neben der for- und der while-Schleife gibt es noch zwei weitere Schleifenformen.

schleife

Beschreibung

do ... while

do
{
Anweisung(en)
} while (Bedingung)

Diese Schleife unterscheidet sich von der while-Schleife dadurch, dass ihr Schleifenkörper unabhängig von der Schleifenbedingung mindestens einmal ausgeführt wird (wird von älteren Browsern nicht unterstützt)

for ... in

Dies ist eine Sonderform der for-Schleife, mit der man bequem alle Elemente in einem Array durchlaufen kann (siehe Abschnitt 9.6.1)

Tabelle 9.10: Weitere JavaScript-Schleifen

9.4 Funktionen

Das Konzept der Funktionen ist nicht mehr ganz neu für uns. Von verschiedenen vordefinierten Funktionen wie write(), parseInt() oder sqrt() haben wir bereits fleißig Gebrauch gemacht4 und im vorangehenden Kapitel haben wir sogar bereits eigene Funktionen für die Ereignisbehandlung erstellt. In diesem Abschnitt wollen wir unser praktisches Wissen auf eine fundierte theoretische Basis stellen.

Die Funktionsdefinition und -aufruf

Eine Funktion zu definieren, bedeutet letzten Endes nichts anderes, als einen Anweisungsblock, der eine bestimmte Aufgabe erfüllt (beispielsweise einen Text ausgibt, die Wurzel einer Zahl berechnet oder den Antwortcode zu einem HTML-Ereignis enthält), mit einem Namen, dem Funktionsnamen, zu verbinden.

Der Vorteil dieses Verfahrens ist, dass man die Funktion nur einmalig irgendwo zu definieren braucht (bevorzugt am Anfang des HTML-Dokuments oder der JavaScript- Datei) und sie später durch Aufruf über ihren Namen ausführen lassen kann. Wir werden dies gleich an einem Beispiel verdeutlichen., zuvor aber noch die formelle Syntax der Funktionsdefinition.

Funktionsdefinition

function demo()
{
Anweisung(en);
}

Funktionsdefinitionen werden mit dem Schlüsselwort function eingeleitet. Darauf folgt der Funktionsname, der mit runden Klammern abgeschlossen wird. (Weiter unten werden wir sehen, wie man in den runden Klammern eine Liste von Parametern definiert, über die die Funktion Werte entgegennehmen kann.) An diesen Funktionskopf schließen sich in geschweiften Klammern die auszuführenden Befehle an.

Funktionsaufruf

Funktionen werden einfach über ihren Namen aufgerufen.

demo();

Beispiel

Das folgende Beispiel enthält eine Webseite mit drei Textabsätzen. Jedes Mal, wenn der Besucher der Webseite mit der Maus über einen dieser Textabsätze fährt, wollen wir die Hintergrundfarbe der Webseite ändern. Der JavaScript-Code hierfür sieht wie folgt aus:

var f = parseInt( 1 + Math.random() * 5);
switch(f)
{
case 1: document.bgColor = "red"; break;
case 2: document.bgColor = "green"; break;
case 3: document.bgColor = "yellow"; break;
case 4: document.bgColor = "cyan"; break;
case 5: document.bgColor = "blue"; break;
}

Zuerst wird eine Zufallszahl zwischen 1 und 5 erzeugt. Zufallszahlen zu erzeugen, ist recht schwer. Wir greifen daher auf die Methode Math.random zurück, die uns eine zufällige Zahl zwischen 0 und 1 zurückliefert.

Zufallszahlen

Echte Zufallszahlen gibt es in der Programmierung nicht. Man kann aber Zahlenfolgen generieren, die sich erst sehr spät wiederholen und kein Muster erkennen lassen. Wenn man nacheinander auf die Zahlen eine solchen Zahlenfolge zugreift, kommt dies dem Ziehen von Zufallszahlen ziemlich nahe. Und genau dies tut die Methode Math.random.

Die von Math.random zurückgelieferte Zahl multiplizieren wir mit 5 (jetzt haben wir eine Zufallszahl zwischen 0 und 5). Dann addieren wir noch 1 (jetzt haben wir eine Zufallszahl zwischen 1 und 6). Zum Schluss wandeln wir die Zahl in eine Ganzzahl um und weisen diese f zu. Die Variable f enthält jetzt einen der Wert 1, 2, 3, 4 oder 5.

Mit Hilfe einer switch-Verzweigung verbinden wir jeden dieser Werte mit einer Hintergrundfarbe.

Jetzt müssen wir diesen Code nur noch mit dem onmouseover-Ereignis der drei Textabsätze verbinden. Wir könnten den Code dazu direkt als Wert des onmouseover-Attributs eintippen, doch bedeutet dies unnötige Tipparbeit und macht den Code der Webseite wegen der Vermischung von HTML- und JavaScript-Code sehr unübersichtlich. Besser ist es, den Code in Form einer Funktion am Anfang der Webseite zu definieren. In den onmouseover-Attributen brauchen wir dann nur noch die Funktion aufzurufen.

Listing 9.10: funktionen1.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<title>Funktionen</title>
<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script type="text/javascript">
function farbe_setzen()
{

var f = parseInt( 1 + Math.random() * 5);
switch(f)
{
case 1: document.bgColor = "red"; break;
case 2: document.bgColor = "green"; break;
case 3: document.bgColor = "yellow"; break;
case 4: document.bgColor = "cyan"; break;
case 5: document.bgColor = "blue"; break;
}
}
</script>

</head>

<body>
<p onmouseover="farbe_setzen()">Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text ... </p>
<p onmouseover="farbe_setzen()">Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text ... </p>
<p onmouseover="farbe_setzen()">Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text ... </p>
</body>
</html>

Im Navigator 4 funktioniert dieses Beispiel so nicht, da der Navigator (im Gegensatz zum Internet Explorer oder Netscape 6-Browser) keine Mausereignisse für Absätze unterstützt. Wenn Sie mit dem Navigator arbeiten, ändern Sie die <p>-Absätze in Hyperlinks der Form: <a href="" onmouseover= "farbe_set- zen()">Text...</a>.

Die Auslagerung des Codes in eine Funktion hat noch einen weiteren Vorteil. Stellen Sie sich vor, Sie wollten die Farbtabelle erweitern oder einfach andere Farben vorsehen. In obigem Listing müssen Sie dazu nur einmal den Code der Funktion überarbeiten. Hätten Sie den Code dreimal in den <p>-Tags der Absätze stehen, müssten Sie die gleichen Änderungen dreimal vornehmen.

Es gibt noch andere Tricks, wie man zufällige Farben erzeugt. In Übung 3 werden Sie einen möglichen Algorithmus kennen lernen.

Parameter an Funktionen übergeben

Unsere in obigem Abschnitt definierte Funktion farbe_setzen() ist eine extrem unkommunikative Funktion, denn sie erlaubt keinen Datenaustausch zwischen sich und dem aufrufenden Code. Viele Funktionen werden aber erst dadurch wirklich wertvoll, dass sie vom Aufrufer zu verarbeitende Daten übernehmen und unter Umständen sogar Ergebniswerte zurückliefern. Wir kennen dieses Verhalten bereits von den vordefinierten Methoden.

In diesem und dem folgenden Abschnitt werden Sie sehen, wie Sie selbst Funktionen schreiben können, die beim Aufruf Werte übernehmen und Ergebnisse zurückliefern.

Soll eine Funktion beim Aufruf einen Wert übernehmen, muss man in der Funktionsdefinition in den runden Klammern einen Variablennamen für diesen Wert angeben.

Parameter und Argumente

Die in den runden Klammern definierten Variablen nennt man Parameter der Funktion. Sie sind nur in der Funktion gültig. Die Werte, die beim Aufruf der Funktion an diese Parameter übergeben werden, bezeichnet man als Argumente. (Es gibt aber auch viele Programmierer und Buchautoren, die in beiden Fällen von Parametern sprechen.)

function farbe_setzen(farbe)
{
document.bgColor = farbe;
}

Diese Funktion dient dazu, die Hintergrundfarbe der Webseite zu setzen. Die Farbe übernimmt sie als Argument. Dadurch, dass die Hintergrundfarbe beim Aufruf angegeben werden kann, ist die Funktion recht flexibel einsetzbar (abgesehen davon, dass man für so triviale Aufgaben wie das Setzen der Hintergrundfarbe keine Funktion benötigt).

Aufruf:

farbe_setzen("red");

oder

onereignis="farbe_setzen('red')"

Call by value

Als Argumente kann man Konstanten oder Variablen übergeben. Wenn Sie Variablen übergeben, stellt sich die Frage, wie die Variable an die Funktion übergeben wird. Eine Möglichkeit wäre, dass die Variable selbst an die Funktion weitergereicht wird. Parameter und Variable wären dann identisch und die Funktion könnte über den Parameter den Wert der Variablen ändern. Man bezeichnet dies als call by reference, und wir sagen Ihnen gleich, dass dieses Verfahren von JavaScript nicht verwendet wird. JavaScript verwendet stattdessen das call by value-Verfahren, bei dem der Parameter als Kopie der Variablen erstellt wird. Das heißt, beim Aufruf wird der Wert der Variablen in den Parameter kopiert. Wenn später in der Funktion dem Parameter ein neuer Wert zugewiesen wird, ändert sich nur der Wert des Parameter, nicht der Wert der Variablen, die im Aufruf angegeben wurde.

Mehrere Parameter

Eine Funktion kann auch mehrere Parameter übernehmen. Diese werden dann durch Kommata getrennt in den runden Klammern aufgelistet.

function demo(par1, par2, par3)
{
Anweisung(en);
}

Beim Aufruf der Funktion werden den Parametern die passenden Argumente übergeben: ebenfalls durch Kommata getrennt und in der gleichen Reihenfolge.

Werte aus Funktionen zurückliefern

So einfach die Übergabe von Werten an die Funktion ist, so einfach ist auch das Zurückliefern eines Wertes aus der Funktion. Sie brauchen dem zurückzuliefernden Wert lediglich das Schlüsselwort return voranzustellen:

return ergebnis_wert;

Das folgende Listing ist eine überarbeite Version des Listing 9.8.

Listing 9.11: funktionen2.html - Werte übernehmen und zurückliefern

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Funktionen</title>
</head>

<body>
<h1>Die Quadratzahlen</h1>

<script type="text/javascript">

function quadrat(zahl)
{
var quadrat;

quadrat = loop * loop;
return quadrat;
}

var loop;

for (loop=1; loop <= 10; ++loop)
{
document.write("<p>Das Quadrat von ");
document.write(loop);
document.write(" ist ");
document.write(quadrat(loop));
document.write(".</p>");
}

</script>

</body>
</html>

Eine Funktion kann immer nur einen Wert als Ergebniswert zurückliefern. Dies bedeutet aber nicht, dass sie nur eine return-Anweisung enthalten kann. Eine Funktion kann durchaus mehrere return-Anweisungen enthalten - beispielsweise um in Abhängigkeit von einer if-Bedingung verschiedene Ergebniswerte zurückzuliefern.

function demo()
{
...
if(Bedingung)
{
...
return true;
}
else
{
...
return false;
}
}

Abbildung 9.6:  Mit Hilfe einer Funktion und einer Schleife erzeugte Ausgabe

9.5 Klassen und Objekte

Bisher gehörten alle von uns definierten Variablen dem einen oder anderem Standarddatentyp von JavaScript an (siehe Tabelle 9.3). JavaScript erlaubt aber auch die Definition eigener Datentypen - und zwar in Form von Klassen.

Die Definition von Klassen führt uns zur objektorientierten Programmierung, der bei der modernen Software-Erstellung eine immer größere Bedeutung zukommt (weswegen professionell eingesetzte Programmiersprachen wie C++ oder Java alle objektorientiert sind). Für die Programmierung mit JavaScript ist die objektorientierte Programmierung bei weitem nicht so wichtig. Dies liegt daran, dass JavaScript-Skripte meist so kurz und unkompliziert sind, dass sich die Definition von Klassen selten lohnt. Sie werden daher selten in die Verlegenheit geraten, eigene Klassen zu definieren, und Sie werden auch nur selten über Skripte stolpern, in denen andere JavaScript-Programmierer dies getan haben. Trotzdem lohnt sich die Auseinandersetzung mit den objektorientierten Konzepten, denn wenn wir auch keine eigenen Klassen und Objekte definieren, so müssen wir doch häufig auf die vom Interpreter erstellen Klassen und Objekte zurückgreifen - beispielsweise window, document, Math, etc. Ich sage »müssen«, dabei ist es im Grunde ein Vorteil für uns, dass JavaScript diese Dinge in Form von Klassen und Objekten zur Verfügung stellt, denn die Programmierung wird dadurch logischer und einfacher. Wenn Sie sich erinnern, wie einfach es ist, über document.write() einen Text auszugeben oder mit document.bgColor die Hintergrundfarbe einer Webseite festzulegen, werden Sie dies sicherlich bestätigen.

Um die Arbeit mit Klassen, Objekten und ihren Methoden und Eigenschaften aber noch besser verstehen zu können, tauchen wir jetzt ein in die Welt der Klassen und Objekte.

Klassen und Objekte

Klassen sind im Grunde Beschreibungen von Dingen, mit denen ein Programm arbeiten möchte. Man kann sich das in etwa wie beim Zinnfigurengießen vorstellen. Nehmen wir an Sie wollen irgendeine historische Schlacht nachstellen. Das Erste, was Sie machen, ist sich für die beteiligten Figuren (Soldaten und Offiziere der beteiligten Länder, Kanonen, Pferde, etc.) Gussformen zu kaufen. Danach gehen Sie daran, die Figuren zu gießen, zu bemalen und aufzustellen. Ranghohe Offiziere werden Sie nur wenige Male gießen, einfache Soldaten oder Reiter werden sie öfters gießen.

Übertragen auf ein JavaScript-Programm entsprechen die Gussformen den Klassen. Wenn Sie ein Programm schreiben würden, das die betreffende Schlacht simuliert, würden Sie für die beteiligten Figuren keine Gussformen erwerben, sondern Klassen definieren. Und statt aus den Gussformen die eigentlichen Figuren zu gießen, erzeugen Sie in Ihrem Programm die Figuren als Objekte der Klassen - einen Vorgang, den man auch als Instanzbildung bezeichnet. Klassen für die ranghöheren Offiziere werden Sie nur wenige Male instantiieren, während Sie auf der Grundlage der Klassen für Soldaten, Pferde oder Kanonen sicherlich mehrere Objekte erzeugen werden.

Wie die Figuren, die aus einer Form gegossen werden, sind auch die Objekte einer Klasse alle gleich. Die Objekte der Klasse Major sind alles Majore, die Objekte der Klasse Soldat sind alles Soldaten. Die einzelnen Objekte einer Klasse können aber durchaus individuelle Züge aufweisen. Nehmen wir die einfachen Soldaten. Die gegossenen Zinnsoldaten können Sie beispielsweise bemalen, um so den einzelnen Soldatenfiguren Individualität zu verleihen (wobei die Figur immer noch ein Soldat, sprich ein Guss der Form Soldat, bleibt). Die Objekte der Klasse Soldat kann man natürlich nicht bemalen, aber sie verfügen über bestimmte Eigenschaften, die in der Klasse definiert sind (beispielsweise Name, Alter, Haarfarbe). Diesen Eigenschaften kann man individuelle Werte zuweisen.

Klassen definieren

Klassen werden in JavaScript durch Definition einer passenden »Konstruktorfunktion« angelegt. Der Name der Konstruktorfunktion ist auch der Name der Klasse.

Eigenschaften

Im Konstruktor werden die Eigenschaften der Klasse definiert. Allerdings werden die Eigenschaften nicht mit dem Schlüsselwort var definiert (wie man vielleicht annehmen könnte), sondern mit Hilfe des Schlüsselworts this.

Das Schlüsselwort this kann in Konstruktoren- und Methodendefinitionen von Klassen verwendet werden und bezeichnet das jeweils aktuelle Objekt (für das der Konstruktor/die Methode später zur Laufzeit aufgerufen wird).

function MeineKlasse()
{
this.eigenschaft1 = wert;
...

Dabei wird der Eigenschaft üblicherweise auch gleich ein Wert zugewiesen. Den Wert können Sie direkt angeben (siehe oben). Sie können aber auch im Konstruktor einen Parameter für die Eigenschaft definieren und der Eigenschaft dann den Parameter zuweisen. Letztere Vorgehensweise hat den Vorteil, dass man den Eigenschaften später bei der Erzeugung der Objekte Werte zuweisen kann.

function Personalien(name, vorname, alter)
{
this.name = name;
this.vorname = vorname;
this.alter = alter;
this.hobbys = "unbekannt";
}

Methoden

Methoden werden ähnlich wie Eigenschaften definiert. Als Wert weist man ihnen den eigenen Methodennamen zu. Anschließend wird die Methode unterhalb der Konstruktorfunktion definiert.

function Personalien(name, vorname, alter)
{
this.name = name; // Eigenschaft
this.vorname = vorname; // Eigenschaft
this.alter = alter; // Eigenschaft
this.hobbys = "unbekannt"; // Eigenschaft
this.write = write; // Methode
}

function write() // Methodendefinition
{
document.write(this.vorname + " ");
document.write(this.name + ", ");
document.write(this.alter + ", ");
document.write("Hobbys: " + this.hobbys);
}

Objekte erzeugen

Um Objekte einer Klasse zu erzeugen, benutzt man das Schlüsselwort new, ruft den Konstruktor auf und übergibt diesem Werte für die Eigenschaften des Objekts.

angestellter = new Personalien("Louis", "Dirk", 34);

Auf Klassenelemente zugreifen

Um auf die Eigenschaften oder Methode eines Objekts zuzugreifen, verwendet man den Punkt-Operator. Diesen setzt man zwischen den Objektnamen und den Namen der Eigenschaft oder Methode

angestellter.hobbys = "Schach, China, Volleyball";
angestellter.write();

with-syntax

Wenn Sie in mehreren, aufeinander folgenden Anweisungen auf die Eigenschaften und/ oder Methoden eines Objekts zugreifen möchten, brauchen Sie nicht immer das Objekt voranzustellen.

Statt

angestellter.name = "Hiller";
angestellter.vorname = "Angus";
angestellter.alter = 42;
angestellter.hobbys = "Angeln";

können Sie auch schreiben:

with (angestellter)
{
name = "Hiller";
vorname = "Angus";
alter = 42;
hobbys = "Angeln";
}

Zugriff innerhalb der Klasse

Will man innerhalb einer Methodendefinition auf andere Elemente (Eigenschaften oder Methoden) der gleichen Klasse zugreifen, braucht man kein vorangehendes Objekt, sondern kann das Element direkt über seinen Namen ansprechen.

Beispiel

In einem zusammenhängenden Beispiel sieht dies dann folgendermaßen aus:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<title>Klassen</title>
<meta http-equiv="Content-Script-Type" content="text/javascript" />

<script type="text/javascript">

// Definition der Klasse Personalien
function Personalien(name, vorname, alter)
{
this.name = name; // Eigenschaft
this.vorname = vorname; // Eigenschaft
this.alter = alter; // Eigenschaft
this.hobbys = "unbekannt"; // Eigenschaft
this.write = write; // Methode
}

function write() // Methodendefinition
{
document.write(this.vorname + " ");
document.write(this.name + ", ");
document.write(this.alter + ", ");
document.write("Hobbys: " + this.hobbys);
}
</script>

</head>

<body>
<p>
<script type="text/javascript">
// Erzeuge angestellter als Objekt der Klasse Personalien
angestellter = new Personalien("Louis", "Dirk", 34);

// Ändere die Eigenschaft hobbys
angestellter.hobbys = "Schach, China, Volleyball";

// Rufe die Methode write auf
angestellter.write();
</script>
</p>
</body>
</html>

Abbildung 9.7:  Ausgabe von angestellter.write()

9.6 Vordefinierte Klassen und Objekte

Bei der Programmierung stehen Ihnen eine Reihe von Klassen und Objekten zur Verfügung, die Ihnen zum einem verschiedene nützliche Methoden zur Verfügung stellen, zum anderen als Schnittstelle zu den HTML-Elemente der Webseite dienen. Diese Klassen und Objekte kann man grob in drei Kategorien unterteilen:

Wie man aus JavaScript-Code heraus auf HTML-Elemente zugreift, erfahren Sie morgen. Zum Ausklang des heutigen Tages begnügen wir uns mit der Vorstellung der wichtigsten Hilfsklassen und Browser-Objekte.

Die Hilfsklassen

Diese Klassen bieten Lösungen für verschiedene, häufig auftretende Programmieraufgaben an.

Die Array-Klasse

Manchmal möchte man in einem Skript mehrere gleichartige Daten verarbeiten. Das kann sehr mühsam sein, wenn man für jeden zu verarbeitenden Wert eine eigene Variable einrichten muss.

Nehmen wir beispielsweise an, Sie führen auf Ihrer Webseite einen Intelligenztest durch. Es gibt insgesamt zwanzig Aufgaben mit jeweils mehreren Unteraufgaben. Insgesamt sind es hundert Unteraufgaben und für jede dieser Unteraufgaben kann man 1 Punkt erhalten. Wir werden dies hier nicht nachprogrammieren, aber damit Sie eine etwas konkretere Vorstellung davon bekommen, möchte ich kurz anskizzieren, wie man so etwas realisieren könnte. Die einzelnen Aufgaben könnte man als Formulare realisieren. Jedes Formular erhält einen Abschicken-Schalter, den der Besucher der Website anklickt, wenn er die Aufgabe mit allen Unteraufgaben bearbeitet hat. Mit dem Abschicken-Schalter ist ein Skript verbunden, dass die Aufgaben auswertet, indem es die Punkte für die Unteraufgaben zusammenzählt. Die Punktzahl für die Aufgabe könnte dann in einem hidden-Feld (siehe Kapitel 17.7) des Formulars oder einer globalen JavaScript-Variablen gespeichert werden. Für unser Beispiel nehmen wir an, dass die Werte in globalen JavaScript-Variablen gespeichert werden.

var aufgabe1 = 3;
var aufgabe2 = 7;
var aufgabe3 = 7;
...

Hat der Besucher der Website den Test vollständig ausgefüllt, sollen die Punkte für die zwanzig Aufgaben zusammengezählt und mit 1.6 multipliziert werden. Das Ergebnis wird dann als erreichter Intelligenzquotient ausgegeben werden.5 Als Skript-Code sähe dies dann folgendermaßen aus:

var ergebnis = 0;
ergebnis = aufgabe1 + aufgabe2 + aufgabe3 + aufgabe4 + aufgabe5 +
aufgabe6 + aufgabe7+ aufgabe8 + aufgabe9 + aufgabe10 +
aufgabe11 + aufgabe12 + aufgabe13 + aufgabe14 + aufgabe15 +
aufgabe16 + aufgabe17 + aufgabe18 + aufgabe19 + aufgabe20;

ergebnis *= 1.6;

document.write("<p>Erreichter Intelligenzquotient: ");
document.write(ergebnis);
document.write("</p>");

Die Aufsummierung sieht ziemlich scheußlich aus. Mit Hilfe eines Arrays (zu deutsch auch »Feld« genannt) könnte man dies viel eleganter lösen.

Zu Anfang der Webseite erzeugt man das Array als globales Objekt:

var aufgaben = new Array(20);

Unser Array-Objekt heißt aufgaben. Es wird mit dem new-Operator als Objekt der Klasse Array erzeugt. Aus dem vorangehenden Abschnitt wissen Sie, dass die Erzeugung eines Objekts immer mit dem Aufruf des Konstruktors der Klasse verbunden ist. Der Konstruktor der Klasse Array erwartet eine Zahlenangabe, die ihm anzeigt, wie groß das zu erzeugende Array-Objekt sein soll, sprich wie viele Werte in ihm gespeichert werden sollen. Da wir die Punkte aus zwanzig Aufgaben in dem Array verwalten wollen, übergeben wir als Argument 20.

Wir haben jetzt ein Array-Objekt, das aus 20 Elementen (einzelnen Variablen) besteht.

Abbildung 9.8:  Elemente in einem Array-Objekt6

In den Ereignisbehandlungsfunktionen zu den Abschicken-Schaltern der einzelnen Aufgaben sollen nun den Elementen im Array die erreichten Punktzahlen zugewiesen werden. Die Frage ist nur, wie man auf die einzelnen Elemente im Array zugreifen kann? Nun, zwar haben die Elemente im Array keine eigenen Namen, dafür aber liegen sie nebeneinander in einer festen Reihenfolge im Array.

Man kann daher auf die einzelnen Elemente über einen Index, eine Positionsangabe, zugreifen. Per Definition hat das erste Element im Array dabei den Index 0. Folglich hat das letzte Elemente in einem Array von 20 Elementen den Index 19. Zum Abspeichern der erreichten Punkte in den Elementen des Arrays schreiben wir also:

aufgaben[0] = 3;
aufgaben[1] = 3;
aufgaben[2] = 3;
...

Soweit sieht man noch keinen großen Unterschied zwischen der Programmierung mit einem Array oder einer Reihe von normalen Variablen. Wenn wir allerdings daran gehen, die Werte aus den Elementen aufzuaddieren, erweist sich der indizierte Zugriff auf die Array-Elemente als extrem hilfreich.

var summe = 0;
var loop;

for (loop = 0; loop < 20; ++loop)
{
summe += aufgaben[loop];
}

Der Trick ist, eine Schleife aufzusetzen und die Schleifenvariable als Index für die Array- Elemente zu verwenden.

Das Durchlaufen der Elemente eines Arrays mit Hilfe einer Schleife ist eine so typische und häufig benötigte Konstruktion, dass es dafür sogar eine besondere for-Syntax gibt:

for (loop in aufgaben)
{
summe += aufgaben[loop];
}

Diese Schleife durchläuft automatisch nacheinander alle Elemente im Array. Man braucht sich noch nicht einmal um die korrekte Initialisierung und Überprüfung der Schleifenvariable zu kümmern.

Was kann man noch mit Arrays machen? Tabelle 9.11 gibt Ihnen eine Übersicht.

Operation

Beschreibung

Länge bestimmen

Die Eigenschaft length enthält die Anzahl Elemente im Array.

var feld = new Array(10);
var anzahl = feld.length; // = 10

Elemente ausgeben

Mit Hilfe der Methode join() kann man einen Textstring erzeugen, der alle Elemente im Array enthält. Als Argument kann man der Methode eine Zeichenkombination übergeben, die zum Trennen der Elemente im String verwendet werden soll.

var ausgabe = feld.join(", ");
document.write(ausgabe);

Reihenfolge umkehren

Mit Hilfe der Methode reverse() kann man die Reihenfolge der Elemente im Array umkehren.

feld.reverse();

Array sortieren

Mit Hilfe der Methode sort() kann man die Elemente im Array sortieren.

feld.sort();

Standardmäßig interpretiert die Methode alle Elemente als Strings und sortiert sie lexikographisch. Will man Zahlen als echte Zahlen sortieren, muss man eine passende Vergleichsfunktion aufsetzen, die festlegt, wie je zwei Elemente im Array zu vergleichen sind:

function vergleiche(a, b) {
if (a < b)
return -1;
if (a > b)
return 1;
if (a == b)
return 0;
}

Diese Funktion übergibt man dann sort() beim Aufruf:

feld.sort(vergleiche);

Dynamische Arrays

Arrays können dynamisch wachsen. Sie brauchen dazu nur ein Element mit einem höheren Index zu definieren.

Nehmen wir an, Sie hätten folgendes Array definiert:

var feld = new Array(10);

Um dieses Array um fünf weitere Elemente zu erweitern, brauchen Sie nur zu schreiben:

feld[14] = 0;

Beachten Sie aber, dass die Elemente mit den Indizes 10, 11, 12 und 13 danach undefinierte Werte haben - bevor Sie mit diesen Elementen arbeiten können, müssen Sie Ihnen richtige Werte zuweisen.

Strings als Indizes

Sie können auch Strings als Indizes verwenden. Dazu müssen Sie ein leeres Array definieren:

var feld = new Array();

Danach nehmen Sie nacheinander Elemente in das Array auf, wobei Sie statt Positionszahlen eindeutige Strings zur Indizierung der Elemente verwenden:

feld["Rainer"] = "3986751";
feld["Otto"] = "555312";
feld["Maria"] = "719903";

Tabelle 9.11: Array-Operationen

Zum Abschluss schauen wir uns noch ein kleines Beispielskript an. Mit Hilfe des folgenden Skriptes kann der Besucher der Website den Mittelwert einer Zahlenreihe berechnen (beispielsweise das Temperaturmittel für den letzten Monat, oder seinen Notendurchschnitt, etc.)

Listing 9.12: arrays.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Arrays</title>
</head>

<body>

<h1>Arrays</h1>

<script type="text/javascript">

// Leeres Array-Objekt definieren
var werte = new Array();


// Werte dynamisch einlesen
var eingabe, loop = 0;
var weiter = true;

while (weiter == true)
{
eingabe = prompt("Geben Sie einen Wert ein ('ende' zum Beenden): ",
¬"");

if (eingabe == "ende")
weiter = false;
else
{
werte[loop] = parseFloat(eingabe);
++loop;
}
}


// Summe berechenen und Mittelwert ausgeben
var summe = 0;

for (loop in werte)
{
document.write("<p>Wert: "); // einzelne Werte zur
document.write(werte[loop]); // Kontrolle ausgeben
document.write("</p>");

summe += werte[loop]; // aufsummieren
}

document.write("<p>Mittelwert: ");
document.write(summe / werte.length);
document.write("</p>");
</script>

</body>
</html>

Abbildung 9.9:  Mittelwertberechnung mit Hilfe eines Arrays

Die Date-Klasse

Objekte der Klasse Date repräsentieren Datums- und Zeitangaben.

Ruft man den Konstruktor ohne Parameter auf, wird das Objekt mit dem aktuellen Datum und der augenblicklichen Uhrzeit initialisiert (wozu auf die Systemzeit des Rechners zurückgegriffen wird).

datum = new Date();

Will man ein Date-Objekt für einen speziellen Tag (Uhrzeit) erzeugen, muss man die entsprechenden Daten an den Konstruktor übergeben:

datum = new Date(jahr, monat, tag);                        
datum = new Date(y, m, t, std, min, sec);

Welche Werte Sie für Jahr, Monat, etc. eingeben müssen, können Sie der folgenden Tabelle entnehmen.

Angabe

Werte

Jahr

Vergangene Jahre seit 1900

Monat

0 - 11

Tag

1 - 31

Stunde

0 - 23

Minute

0 - 59

Sekunde

0 - 59

Tabelle 9.12: Zeitangaben für Date-Konstruktor

Beispiel:

geburtstag = new Date(62, 7, 11);  // 11. August 1962

Zum Abfragen und Verändern des Datums stehen folgende Methoden zur Verfügung.

Methode

Beschreibung

getDate()

Liefert Tag im Monat

getDay()

Liefert Wochentag

getHours()

Liefert Stunden

getMinutes()

Liefert Minuten

getMonth()

Liefert Monat

getSeconds()

Liefert Sekunden

getYear()

Liefert Jahr

setDate(Tag)

Setzt den Tag

setHours(Stunden)

Setzt die Stunden

setMinutes(Minuten)

Setzt die Minuten

setMonth(Monat)

Setzt den Monat

setSeconds(Sekunden)

Setzt die Sekunden

setYear(Jahr)

Setzt das Jahr

getTime()

Liefert Anzahl der Millisekunden, die zwischen dem 1.1.1970 0:00 Uhr und dem im Date-Objekt gespeicherten Datum vergangen sind.

Mit Hilfe dieser Methode kann man auch die Differenz zwischen zwei Datumsangaben berechnen.

var diff = date1.getTime() - date2.getTime();

getTimeZoneoffset()

Zeitverschiebung (in Minuten) gegenüber Greenwich Mean Time.

toGMTString()

Wandelt Date-Objekt als GMT-Datum in String um.

toLocaleString()

Wandelt Date-Objekt nach lokaler Zeit in String um.

UTC(j, m, t)
UTC(j, m, t, std, min, sec)

Liefert Anzahl der Millisekunden, die zwischen dem 1.1.1970 0:00 Uhr und dem im Date-Objekt gespeicherten Datum gemäß Greenwich Mean Time vergangen sind.

Tabelle 9.13: Date-Methoden

Die Math-Klasse

Diese Klasse stellt uns eine Reihe von Konstanten (E, LN2, LN10, LOG2E, LOG10E, PI, SQRT1_2, SQRT2) und mathematischen Funktionen (siehe Tabelle) zur Verfügung.

Methode

Beschreibung

abs(x)

Absolutwert

acos(x)

Arkuskosinus

asin(x)

Arkussinus

atan(x)

Arkustangens

atan2(gk, ak)

Arkustangens (für Längen der Gegen- und Ankathete)

ceil(x)

Nächsthöhere Ganzzahl

cos(x)

Kosinus

exp(x)

Exponentialfunktion

floor(x)

Nächstniedrigere Ganzzahl

log(x)

Logarithmus zur Basis e

max(x, y)

Maximum zweier Werte

min(x, y)

Minimum zweier Werte

pow(x, y)

Potenzfunktion (x hoch y)

random(x)

Zufallszahl zwischen 0 und 1, siehe auch Listing 9.10

round(x)

Runden

sin(x)

Sinus

sqrt(x)

Wurzel

tan(x)

Tangens

Tabelle 9.14: Date-Methoden

Sie auch Listing 9.5.

Die String-Klasse

Objekte der Klasse String kann man durch Aufruf des Konstruktors oder durch einfache Zuweisung eines Strings an eine Variable erzeugen.

var text = new String();
var text = new String("Hallo");
var text = "Hallo";

Dass Strings in JavaScript immer Objekte der Klasse String sind, ist von großem Vorteil für uns, denn neben dem +-Operator zum Aneinanderreihen von Strings stellt uns die Klasse String eine Reihe von Methoden zur Bearbeitung von Strings zur Verfügung.

Methode

Beschreibung

charAt(position)

Liefert Zeichen an bestimmter Position in String zurück. Das erste Zeichen steht an der Position 0.

charCodeAt(position)

Liefert den UNICODE-Wert des Zeichens an der angegebenen Position im String zurück. Das erste Zeichen steht an der Position 0.

concat(string1, string2, ...)

Reiht Strings aneinander (wie +-Operator)

indexOf(suchString, pos)

Durchsucht einen String nach einem Teilstring und liefert die Anfangsposition des gesuchten Teilstrings im String zurück. Die Suche beginnt ab der Position pos.

lastIndexOf(suchString, pos)

Funktioniert wie indexOf, durchsucht den String aber von hinten.

localeCompare(string)

Vergleicht den übergebenen String mit dem eigenen String unter Berücksichtigung lokaler Eigenheiten (Umlaute, etc.) Die Rückgabewerte sind implementierungsspezifisch.

match(regExp)

Sucht im String nach Teilstring, die dem regulären Ausdruck regExp entsprechen. Liefert Array der gefundenen Vorkommen zurück.

replace(suchString, ersetzenString)

Sucht im String nach dem Teilstring suchString und ersetzt ihn durch ersetzenString.

search(regExp)

Sucht im String nach Teilstring, die dem regulären Ausdruck regExp entsprechen. Liefert Anfangsposition des gefundenen Teilstrings zurück.

slice(start, ende)

Extrahiert den String zwischen den Positionen start und ende.

split(trennzeichen)

Teilt den String bei jedem Vorkommen des angegebenen Trennzeichens und liefert die Teilstrings als Array zurück.

subString(start, ende)

Liefert den Teilstring zwischen den Positionen start und ende zurück.

toLowerCase()

Umwandlung in Kleinbuchstaben.

toLocaleLowerCase()

Umwandlung in Kleinbuchstaben (unter Berücksichtigung nationaler Eigenheiten)

toUpperCase()

Umwandlung in Großbuchstaben.

toLocaleUpperCase()

Umwandlung in Großbuchstaben (unter Berücksichtigung nationaler Eigenheiten)

Tabelle 9.15: String-Methoden

Als Bonus gibt es noch eine Eigenschaft: length, die Länge des Strings in Zeichen.

Weitere Hilfsklassen

Klasse

Beschreibung

Boolean

Zur expliziten Erzeugung von Booleschen Objekten:

var weitermachen = new Boolean(true);

Function

Alternative Syntax zur Erzeugung einfacher Funktionen:

meineFunkt = new Function("x", "y", "return x*y");

Number

Zur expliziten Erzeugung von Zahlen-Objekten:

var zahl = new Number(123);

RegExp

Klasse zur Erzeugung regulärer Ausdrücke.

Reguläre Ausdrücke sind ein sehr mächtiges Hilfsmittel zum Aufspüren von Textstellen in Strings. Obwohl die Arbeit mit regulären Ausdrücken nicht allzu kompliziert ist (wenn Sie schon einmal Ihr Dateisystem mit *.html nach HTML-Dateien durchsucht haben, haben Sie schon mit regulären Ausdrücken gearbeitet), ist das Thema doch zu umfangreich, um im Rahmen dieses Buches ausführlich behandelt zu werden.

Error

Klasse zur Erzeugung von Fehlerobjekten

Tabelle 9.16: Sonstige JavaScript-Hilfsklassen

Die Browser-Objekte

Die folgenden Objekte werden vom Browser erzeugt und stehen nach dem Laden der Webseite zur Verfügung.

Das window-Objekt

Dieses Objekt repräsentiert das Browserfenster. Abgesehen davon, dass es das übergeordnete Objekt zu den document-, location- und history-Objekten ist (diese sind Eigenschaften des window-Objekts) stellt es uns eine Reihe nützlicher Funktionen zur Verfügung.

Methode

Beschreibung

open(url, name, eigenschaften)

Öffnet ein neues Browserfenster (siehe Kapitel 8.3.5)

Im String eigenschaften können Sie folgende Angaben machen:

"toolbar=yes,scrollbars=no,menubar=no,status=yes, resizable=yes,location=no,directories=no,width=400, height=300"

close()

Schließt das Browserfenster

alert(text)

Ruft ein Meldungsfenster auf (siehe Kapitel 8.3.3)

confirm(text)

Ruft ein Ok/Abbrechen-Dialog auf

prompt(text, vorgabe)

Ruft eine Eingabeaufforderung auf (siehe Übung 1)

setTimeout(funktion, n)

Ruft die angegebene Funktion nach n Millisekunden auf.

Tabelle 9.17: window-Methoden

Das document-Objekt

Dieses Objekt repräsentiert die Webseite. Es enthält eine Reihe von allgemein unterstützten Methoden und Eigenschaften.

Methode

Beschreibung

clear()

Löscht Webseite.

close()

Schließt Webseite. Danach sind keine Ausgaben mit write/writeln mehr möglich.

open()

Öffnet eine Webseite.

write(string)

Ausgabe eines Textes in Webseite.

writeln(string)

Ausgabe eines Textes in Webseite (mit abschließendem Zeilenumbruch

Tabelle 9.18: document-Methoden

Eigenschaft

Beschreibung

alinkColor

Farbe aktivierter Links

anchors[]

Array, über das man auf die Anker-Elemente der Webseite zugreifen kann

applets[]

Array, über das man auf die Applet-Elemente der Webseite zugreifen kann

bgColor

Hintergrundfarbe

cookie

Von der Webseite gesetzte Cookies

domain

Domänenname des Webservers, von dem die Webseite stammt

fgColor

Vordergrundfarbe

forms[]

Array, über das man auf die Formulare der Webseite zugreifen kann

images[]

Array, über das man auf die <img>-Elemente der Webseite zugreifen kann

lastModified

String, der das Datum der letzten Änderung der Webseite enthält

linkColor

Farbe von Hyperlinks

links[]

Array, über das man auf die Hyperlinks der Webseite zugreifen kann

location

Webadresse der Webseite

referrer

URL, von dem der Besucher zu dieser Seite gekommen ist

title

Titel der Webseite

URL

URL der Webseite

vlinkColor

Farbe besuchter Hyperlinks

Tabelle 9.19: document-Eigenschaften

Manche Eigenschaften, beispielsweise die Vordergrundfarbe, können nach dem Laden der Seite nicht mehr geändert werden (sie sind praktisch nur bei der dynamischen Erzeugung neuer Webseiten interessant, siehe Kapitel 8.3.5).

Das location-Objekt

Dieses Objekt enthält Informationen über den Header des Dokuments.

Methode

Beschreibung

reload()

Seite nochmals laden.

replace(URL)

Lädt neue Webseite und löscht die alte Webseite aus der History.

Tabelle 9.20: location-Methoden

Eigenschaft

Beschreibung

hash

Anker eines Hyperlinks

host

Host und Port

hostname

Name des Servers

href

Gesamte URL

pathname

Pfad und Dateiname

port

Portnummer

protocol

Verwendetes Protokoll

search

Eventuell an URL angehängter Suchstring (zur Verarbeitung in CGI-Programmen)

Tabelle 9.21: location-Eigenschaften

Über das location-Objekt können Sie sich über die Herkunft einer Webseite informieren oder eine neue Webseite laden:

function surfe_zu()
{
location.href = "http://www.w3.org/";
}

Das history-Objekt

Liste der URLs, die der Besucher innerhalb des aktuellen Fensters besucht hat.

Methode

Beschreibung

back()

Wechselt zu der Webseite, die in der History-Liste vorangeht.

forward()

Wechselt zu der Webseite, die in der History-Liste nachfolgt.

go(x)

Wechselt zu der Webseite, die x Positionen in der History-Liste entfernt ist. x kann ein negativer oder positiver ganzzahliger Wert sein.

Tabelle 9.22: history-Methoden

Eigenschaft

Beschreibung

length

Anzahl der Einträge in History-Liste

Tabelle 9.23: history-Eigenschaften

Mit Hilfe des history-Objekts können Sie nicht nur zu anderen Webseiten wechseln, Sie können auch die aktuelle Webseite neu laden lassen:

function aktualisiere()
{
history.go(0);
}

Das navigator-Objekt

Über dieses Objekt können Sie sich über den vom Besucher Ihrer Webseite verwendeten Browser informieren.

Methode

Beschreibung

javaEnabled()

Liefert true, wenn der Browser Java unterstützt.

Tabelle 9.24: navigator-Methoden

Eigenschaft

Beschreibung

appCodeName

Codename des Browsers

appName

Name des Browsers

appVersion

Version des Browsers

mimeTypes[]

Vom Browser unterstützte MIME-Typen

platform

Plattform, für die der Browser erstellt wurde

plugins[]

Array der installierten Plug-Ins

userAgent

Kombination von appCodeName und appVersion-Informationen

Tabelle 9.25: navigator-Eigenschaften

Die Abfrage des verwendeten Browsers (und möglicherweise auch der Browser-Version) ist vor allem dann wichtig, wenn Sie JavaScript-Techniken verwenden, die in den verschiedenen Browsern auf verschiedene Weise durchgeführt werden. Am morgigen Tag werden wir auf diesen Themenbereich ausführlich eingehen.

9.7 Zusammenfassung

Heute haben wir uns mit der JavaScript-Syntax beschäftigt. Für einige Leser wird dies nicht nur der Einstieg in JavaScript, sondern auch der Einstieg in die Programmierung überhaupt gewesen sein. Deshalb sollten wir kurz die wichtigsten Konzepte der Programmierung mit höheren Programmiersprachen wiederholen. (Wenn es auch - insbesondere im Bereich der Künstlichen Intelligenz - Programmiersprachen gibt, die auf anderen Konzepten aufbauen, kann man die an diesem Tag vorgestellten Konzepte in vielen aktuellen Programmiersprachen wiedererkennen.)

Programme dienen allgemein der Datenverarbeitung. Diese Daten können in einem Programm in Form von Konstanten oder Variablen repräsentiert werden.

Variablen sind letztendlich Aliase für Speicherbereiche, in denen man Werte (Daten) abspeichern kann. Nach Art und Aufbau der Daten unterscheidet man verschiedene Datentypen: Boolesche Daten, Ganzzahlen, Fließkommazahlen, Strings. Im Gegensatz zu streng typisierten Programmiersprachen wie C++ oder Java, die für jeden dieser Datentypen eigene Variablentypen kennen, gibt es in JavaScript nur einen Art von Variablen, der man Werte jedes beliebigen Datentyps zuweisen kann. Trotzdem unterscheidet auch JavaScript zwischen den verschiedenen Datentypen. So kann man beispielsweise am Format einer Konstanten ablesen, von welchem Datentyp sie ist. Zudem sind die meisten Operatoren datentypspezifisch.

Mit Hilfe von Operatoren kann man Daten verarbeiten: Man kann sie an Variablen zuweisen, man kann aus ihnen neue Daten berechnen, man kann sie vergleichen.

Vergleiche von Daten werden meist in Verbindung mit Verzweigungen oder Schleifen ausgeführt. Dabei geht es darum, je nach dem Ergebnis eines Vergleichs den einen oder anderen Anweisungsblock auszuführen (Verzweigung) beziehungsweise einen Anweisungsblock mehrfach ausführen zu lassen (Schleife).

Um Code besser strukturieren zu können, verwendet man Funktionen. Ist man gezwungen, eine bestimmte Aufgabe an mehreren Stellen in einem Programm auszuführen (beispielsweise Berechnung des Ergebnisses einer Formel), ist es besser, den Code einmalig in Form einer Funktion zu implementieren und dann die Funktion aufzurufen statt jedes Mal, wo die Berechnung benötigt wird, den Code einzukopieren. (Letzteres Verfahren ist aufwendiger, fehleranfälliger und wenig wartungsfreundlich.) Über Parameter können Funktionen Daten übernehmen, über ihren Rückgabewert können die Funktionen Daten an den aufrufenden Code zurückliefern.

Möchte man komplexere Daten als nur einzelne Zahlen oder Strings verarbeiten, definiert man Klassen. Klassen bestehen aus einer Reihe von Daten (Eigenschaften genannt), bei denen es sich um Daten der elementaren Datentypen oder um Objekte anderer Klassen handeln kann, und klassenspezifischen Funktionen (Methoden genannt), die gewissermaßen die Operatoren darstellen, über die man die Objekte der Klasse bearbeiten kann. (In manchen Sprachen, beispielsweise C++, kann man auch klassenspezifische Implementierungen für Operatoren definieren.) »Werte« vom Typ einer Klassen bezeichnet man als Objekte.

JavaScript definiert eine Reihe von nützlichen Klassen für viele häufig auftretende Programmierprobleme (Array, String, Math, RegExp). JavaScript-fähige Browser stellen eine Reihe von Objekten für die Skriptprogrammierung zur Verfügung: window, document, navigator, location, history.

9.8 Fragen und Antworten

Frage:
Ich habe schon JavaScript-Variablen gesehen, die ein Dollarzeichen enthielten. Sollte das nicht eigentlich ein Fehler sein?

Antwort:
Nein, seit JavaScript 1.1 ist neben dem Unterstrich auch das Dollarzeichen in Bezeichnern erlaubt. Das Dollarzeichen sollte aber laut ECMA-Standard möglichst nicht von Programmierern verwendet werden. Bedenken Sie auch, dass ältere JavaScript-Interpreter das Dollarzeichen in Bezeichnern nicht akzeptieren.

Frage:
Wenn ein unbekannter Bezeichner auf der linken Seite einer Zuweisung auftaucht, erzeugt der Interpreter automatisch eine neue Variable für den Bezeichner. Was aber passiert, wenn ein unbekannter Bezeichner in einem Ausdruck (also als R-Wert) auftaucht?

Antwort:
In so einem Fall brechen die meisten Browser die JavaScript-Bearbeitung ab.

Frage:
Wenn man die Anweisungen zu einer case-Marke nicht mit einer break-Anweisung abschließt, werden auch die nachfolgenden Anweisungen ausgeführt. Meist ist dies unerwünscht, weswegen wir die Anweisungen zu den case-Marken grundsätzlich mit break; abschließen. Aber vielleicht könnte man dieses »Durchfallen« von case-Marke zu case-Marke ja auch irgendwie sinnvoll nutzen?

Antwort:
Ja, wenn Sie beispielsweise für die Werte 1, 2, 3 und 4 den jeweils gleichen Code ausführen wollen, können Sie schreiben:

switch(variable)
{
case 1:
case 2:
case 3:
case 4: // tue etwas; break;
case 5: // tue etwas anderes;
}

Frage:
Ich kann das Beispiel mit der switch-Verzweigung nicht nachvollziehen. Mein Browser führt sie nicht aus!

Antwort:
In früheren JavaScript-Versionen gab es noch keine switch-Verzweigung. Entsprechend wird die switch-Verzweigung nicht von älteren Browsern unterstützt. Sollten Sie einen neueren Browser verwenden, prüfen Sie, ob Sie nicht vielleicht doch irgendwo einen Tippfehler eingebaut haben.

Frage:
Kann ich in einem Array Werte unterschiedlicher Datentypen speichern, beispielsweise Zahlen und Strings?

Antwort:
Ja, das geht, aber man sollte es möglichst vermeiden. Der Hauptvorteil der Arrays ist, dass man die Elemente im Array in einer Schleife durchlaufen und bearbeiten kann. Das geht aber nicht mehr, wenn im Array ganz unterschiedliche Daten abgespeichert sind, die nicht in dergleichen Weise verarbeitet werden können.

9.9 Workshop

Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, und Übungen, die Sie anregen sollen, das eben Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Versuchen Sie, das Quiz und die Übungen zu beantworten und zu verstehen, bevor Sie zur Lektion des nächsten Tages übergehen.

Quiz

  1. Welche der folgenden Variablennamen sind keine gültigen Bezeichner?
    var hallo;
    var drei!;
    var 3fach;
    var Hallo;
    var guter-Wert;
    var Gärung;
    var new;
    var newWert;
  2. Für welche Werte stehen die folgenden Ausdrücke, wenn wert1 = 13, wert2 = 4, wert3 = 1.5, wert4 = "23"?
    wert1 / wert2;               // 3.25
    wert1 % wert2; // 1
    wert1 / wert3; // 8.6666
    wert1 + wert4 * wert3; // 47.5
    (wert1 + wert4) * wert3; // 1984.5
  3. Was ist falsch an der folgenden Schleife?
    var loop = 1;
    var ergebnis = 0;

    while(loop <= 10)
    {
    ergebnis = loop*loop*loop;
    if (ergebnis > 700)
    continue;
    document.writeln(ergebnis);
    ++loop;
    }
  4. Sie wollen eine Reihe von Messwerten verarbeiten. Welche Datenstruktur wählen Sie zur Verwaltung der Messwerte in Ihrem Skriptcode?
  5. Sie wollen zusammengehörende Daten unterschiedlicher Datentypen verarbeiten (beispielsweise Personendaten: Name, Vorname, Alter, Haarfarbe). Welche Datenstruktur wählen Sie zur Verwaltung der Adressen in Ihrem Skriptcode?

Übungen

  1. Implementieren Sie ein JavaScript, das beim Aufruf der Webseite ein Passwort abfragt und mit Hilfe einer if-Bedingung sicherstellt, dass nur ausgewiesene Besucher den Inhalt der Webseite zu sehen bekommen.
  2. Wandeln Sie die folgende for-Schleife in eine while-Schleife um.
    // Umrechnung Fahrenheit in Celsius
    var fahrenheit = 0;
    var celsius = 0;

    for (fahrenheit = -30; fahrenheit <= 90; fahrenheit += 10)
    {
    celsius = (fahrenheit - 32) * 5 / 9;
    document.write("<p>" + fahrenheit + " Fahrenheit entsprechen "
    + celsius + " Grad Celsius</p>");
    }
  3. Schreiben Sie Listing 9.10 so um, dass in dem Skriptcode vollkommen zufällige RGB- Farben ausgewählt werden.



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


123456

© Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH