This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Das Kompendium Die Reihe für umfassendes Computerwissen Seit mehr als 20 Jahren begleiten die KOMPENDIEN aus dem Markt+Technik Verlag die Entwicklung des PCs. Mit ihren bis heute über 500 erschienenen Titeln deckt die Reihe jeden Aspekt der täglichen Arbeit am Computer ab. Die Kompetenz der Autoren sowie die Praxisnähe und die Qualität der Fachinformationen machen die Reihe zu einem verlässlichen Partner für alle, ob Einsteiger, Fortgeschrittene oder erfahrene Anwender. Das KOMPENDIUM ist praktisches Nachschlagewerk, Lehr- und Handbuch zugleich. Auf bis zu 1.000 Seiten wird jedes Thema erschöpfend behandelt. Ein detailliertes Inhaltsverzeichnis und ein umfangreicher Index erschließen das Material. Durch den gezielten Zugriff auf die gesuchte Information hilft das KOMPENDIUM auch in scheinbar aussichtslosen Fällen unkompliziert und schnell weiter. Praxisnahe Beispiele und eine klare Sprache sorgen dafür, dass bei allem technischen Anspruch und aller Präzision die Verständlichkeit nicht auf der Strecke bleibt. Mehr als 5 Millionen Leser profitierten bisher von der Kompetenz der KOMPENDIEN.
Unser Online-Tipp für noch mehr Wissen ...
... aktuelles Fachwissen rund um die Uhr — zum Probelesen, Downloaden oder auch auf Papier.
www.InformIT.de
JavaScript Interaktives und dynamisches Webpublishing TOBIAS HAUSER
(
KOMPENDIUM Einführung I Arbeitsbuch I Nachschlagewerk
)
eBook Die nicht autorisierte Weitergabe dieses eBooks an Dritte ist eine Verletzung des Urheberrechts!
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar. Die Informationen in diesem Buch werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Texten und Abbildungen wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig auch eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Buch wurde auf chlorfrei gebleichtem Papier gedruckt.
Sie sollten dieses Buch lesen, wenn Sie eine solche Fehlermeldung öfter mal produzieren …
Wer sollte dieses Buch noch lesen? Für dieses Buch brauchen Sie von JavaScript noch nichts zu wissen. Sie lernen die Grundlagen, beginnend mit dem Einbau von Skripten in HTML. Der Einstieg erfolgt in aufeinander aufbauenden Schritten. Eine Vorraussetzung gibt es allerdings doch: Sie sollten HTML beherrschen oder sich zumindest parallel aneignen. Wenn Sie bereits fortgeschrittener JavaScript-Programmierer sind, wissen Sie, dass es im Internet Tausende von fertigen Skripten gibt. Das Problem ist nicht, fündig zu werden, sondern die Skripte zuerst qualitativ zu beurteilen, dann auf die eigenen Bedürfnisse anzupassen und abzuwandeln. Dazu ist Hintergrundwissen und Sachkenntnis erforderlich, die Sie sich mit Hilfe dieses Buches aneignen können. Zugegeben, dicke Bücher sind schwer zu tragen, aber wenn Sie sich dieses Buch ins Regal stellen, haben Sie auf jeden Fall auch noch lange nach dem Einstieg in JavaScript ein gutes Nachschlagewerk. Und der Weg vom Regal zum Schreibtisch ist ja normalerweise überschaubar .
KOMPENDIUM
JavaScript
23
Vorwort
Inhalt Das Buch ist in drei Teile unterteilt und besitzt einen Anhang. Ein Überblick zeigt Ihnen, was Sie erwartet: Teil 1 enthält die Grundlagen von JavaScript und behandelt alle nötigen Bausteine für fortgeschrittenes Programmieren. Die Kapitel von Teil 1 hängen inhaltlich zusammen und bauen aufeinander auf. Sollte der geneigte Leser allerdings einzelne Teile daraus später benötigen, findet er sich auch beim direkten Nachschlagen gut zurecht. Teil 2 zeigt häufige, wichtige und interessante Webanwendungen von Bildern über Formulare, Fenster, Cookies und DHTML. Alle relevanten Themen werden ausführlich und detailliert behandelt. Teil 3 auf den gelben Seiten wirft einen Blick über den Tellerrand, erklärt Sicherheitsaspekte und die Kommunikation von JavaScript mit Java, Multimedia-Plugins und Flash. Abgerundet wird der Teil durch einen Blick auf serverseitiges JavaScript mit JScript .NET. Im Anhang finden Sie Informationen über Browser und Tools, Sie werfen einen Blick in die Zukunft und erhalten nützliche Quellen. Den Abschluss bildet der Inhalt der Buch-CD-ROM, die nicht nur schmückendes Beiwerk, sondern praktische Hilfe für Sie sein soll.
Browser Eine der Kernfragen für JavaScript-Entwickler ist nach wie vor, welche Funktionen in welchen Browsern zur Verfügung stehen. Dieses Buch beschreitet hier einen neuen Weg: Sie finden am Ende keine dicke Referenz, sondern stattdessen bei allen wichtigen Elementen von JavaScript eine Tabelle über die Browserkompatibilität: Tabelle 0.1: alert()
NS4x
NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Darin sehen Sie auf einen Blick, für welchen Browser das jeweilige Sprachelement vorhanden ist. Gegenüber normalen Übersichten wurden zusätzlich zu den Standardbrowsern Netscape Navigator (NS, gefolgt von Versionsnummer) und Internet Explorer (IE, gefolgt von Versionsnummer) noch die »Exoten« Opera 7.x, Mozilla (M, Version 1.x) und Konqueror (K, Version 3.x) hinzugenommen. Ältere Versionen von Netscape Navigator und Internet Explorer haben in der Tabelle keinen Platz gefunden und augrund des nicht mehr vorhandenen Marktanteils auch nicht unbedingt verdient. Falls erforderlich, werden sie allerdings im Vortext zu den Tabellen erwähnt. 24
KOMPENDIUM
JavaScript
Service
Vorwort
Service Auf dem Weg zum JavaScript-Profi werden Sie beim Lesen einige Icons unterstützen: Dieses Symbol deutet an, dass Sie hier zusätzliche Informationen finden.
Einen Verweis auf eine andere Stelle, die für ein Thema ebenfalls von Interesse ist oder einen Themenbereich vertieft, finden Sie bei diesem Symbol. Achtung, hier versteckt sich eine Falle oder eine Information, die Ihre besondere Aufmerksamkeit erfordert. Egal ob schnellere Lösung oder zusätzliche Möglichkeiten: Informationen neben diesem Symbol geben nützliche Tipps. Dieses Icon deutet an, dass auf der Buch-CD-ROM eine passende Datei liegt. Meist sind dies Dateien, die vorhandene Listings abwandeln und weitere Alternativen aufzeigen oder die für Beispiele im Buch benötigt werden. Insgesamt finden Sie über 400 Listings auf der CD-ROM. Alle Beispiele in diesem Buch befinden sich auf der CD-ROM. Die Namen der Beispieldatei entnehmen Sie der Listingunterschrift. Im abgedruckten Code sind wichtige Stellen fett hervorgehoben, um Ihnen die Übersicht zu erleichtern.
Listing 0.1: Ein Beispiel (beispiel.html)
Neben allen Listings und zusätzlichen Beispieldateien finden Sie außerdem eine Menge nützlicher Software auf der CD. Eine Übersicht vermittelt Anhang E »CD-ROM«.
Hilfe Der Kerngedanke dieses Buches ist es, dem (angehenden) JavaScript-Entwickler das bestmögliche Hilfsmittel mitzugeben. Sollten Sie als JavaScriptEntwickler und Leser dieses Buches: etwas vermissen, einen Fehler finden, eine Anregung loswerden wollen oder einfach nur eine Meinung zum Buch haben, schreiben Sie mir eine E-Mail an [email protected].
KOMPENDIUM
JavaScript
25
Vorwort Neuigkeiten und eine Errataliste zum Buch finden Sie auf der Website zum Buch http://www.hauser-wenz.de/go/javascript-kompendium. Leider kann ich nur Fragen beantworten, die sich direkt um den Inhalt dieses Buches drehen. Dafür versuche ich aber, die Antwortzeiten so kurz wie möglich zu halten.
Team Dass dieses Buch heute in Ihren Händen liegt, verdanken Sie als Leser und noch viel mehr ich als Autor vielen Menschen, die den Entstehungsprozess ganz oder teilweise begleitet haben: Meinem Lektor Jürgen Bergmoser für sein Engagement und den Glauben an das Projekt. Meiner Korrektorin Monika Hardt, die auch bei großer Zeitknappheit den Duden nicht aus den Augen verloren hat. Christian für seine Unterstützung und viele wertvolle Anregungen. Stefanie für aufopferungsvolle Kampfbereitschaft und Kuchen. Claudia und Rudi für ein wenig Entspannung in der heißen Phase. Marianne. Vielen Dank! Und zum Schluss noch ein Dank an Sie, lieber Leser! Denn für Sie ist dieses Buch geschrieben. Tobias Hauser Starnberg, Frühjahr 2003
26
KOMPENDIUM
JavaScript
Team
Vorwort
Schreiben Sie uns! Autor und Verlag sind immer bemüht Ihnen, unseren Kunden und Lesern die optimale Information zum Thema zu bieten. Scheuen Sie sich deshalb nicht, uns über Fehler und andere Ärgernisse zu informieren. Nur so können wir laufend an der Verbesserung unserer Bücher arbeiten. Aber auch Lob, Erfolgserlebnisse und Ihre Ergebnisse interessieren uns. Schreiben Sie uns unter [email protected], Ihre Mails werden sofort an den Autor weitergeleitet! Ihr Markt+Technik-Buchlektorat Jürgen Bergmoser [email protected]
KOMPENDIUM
JavaScript
27
Teil 1 JavaScript
Kapitel 1:
Wissenswertes
31
Kapitel 2:
JavaScript in HTML
37
Kapitel 3:
Syntax und Variablen
57
Kapitel 4:
Programmieren
81
Kapitel 5:
Funktionen
131
Kapitel 6:
Objekte
159
Kapitel 7:
Arrays und Strings
207
Kapitel 8:
OOP
253
Kapitel 9:
Debugging
283
Kapitel 10: Document Object Model
305
Kapitel 11: Ereignisse und Event-Handler
339
1
Wissenswertes
Das World Wide Web wäre ohne JavaScript nicht denkbar. Wenn Sie einen Blick in den Quellcode irgendeiner größeren Website werfen, sehen Sie dort sicherlich einen <script>-Block mit JavaScript-Code. Dieser Code wird im Browser interpretiert (ausgeführt) und ist clientseitig, da das Ausführen des Codes auf dem Rechner des Nutzers (Client) geschieht.
Server Webserver
Response
Abbildung 1.1: Die (vereinfachte) Client-ServerArchitektur
Request
JavaScriptInterpreter
Client
Browser JavaScript ist im Web für die verschiedensten Aufgaben verantwortlich: für Rollover-Effekte, für das Ändern mehrerer Frames mit einem Link, für die Vollständigkeitsüberprüfung von Formularen, für Warenkörbe, Navigationselemente und Animationen. All diese Anwendungen erfüllen hauptsächlich einen Zweck: Webseiten zu verbessern, interaktiver zu gestalten und komfortabler zu machen. Zum Erfolg von JavaScript hat sicherlich auch beigetragen, dass es clientseitig nahezu konkurrenzlos ist. Im Internet Explorer können Sie zwar noch VBScript (Visual Basic Script) verwenden, allerdings bleibt es auf den Internet Explorer beschränkt und schließt damit viele Browser aus.
KOMPENDIUM
JavaScript
31
Kapitel 1
Wissenswertes
1.1
Historie
Vor dem Erfolg von JavaScript stand eine wechselhafte Geschichte: Der erste kommerzielle Webbrowser wurde im Jahr 1995 von der Firma Netscape1 entwickelt. Relativ bald darauf entstand die Idee für eine Skriptsprache. Sie sollte im Browser, aber auch in den Webserver-Produkten von Netscape eingesetzt werden und trug den Namen LiveScript. Der Leiter des damaligen Projektteams war Brendan Eich, der als Vater von JavaScript gilt. Zu diesem Zeitpunkt wurde Java, eine recht komplexe Programmiersprache von Sun, sehr erfolgreich. Netscape dachte sich, die neue Skriptsprache könnte von diesem Erfolg profitieren, schloss eine Vereinbarung mit Sun und benannte LiveScript in JavaScript um. Dieser Schritt war ein Fehler, der heute noch seine Schatten wirft. JavaScript wird in vielen Diskussionen, Beiträgen und Pamphleten mit Java gleichgesetzt, was in keinster Weise richtig ist. Die Syntax von JavaScript mag Ähnlichkeiten mit der von Java haben, da aber Java schon auf C und C++ basiert, kann man solche Ähnlichkeiten zwischen fast allen heute verwendeten Skript- und Programmiersprachen finden. Dankenswerterweise konnte sich JavaScript freischwimmen und hat seinen Erfolgsweg trotzdem eingeschlagen2. Microsoft merkte spätestens beim erfolgreichen Börsengang von Netscape, dass das Web und der Browser große Zukunftschancen haben und zog deswegen mit einem eigenen Browser, dem Internet Explorer, nach. Die ersten ernst zu nehmenden Versionen des Internet Explorer sind zwei Auslieferungen der Version 3. Sie besitzen einige JavaScript-Fähigkeiten beispielsweise für Bilder. Leider trug nun auch Microsoft zur Namenskonvention von JavaScript bei: Aus Lizenz-rechtlichen Gründen nannte Microsoft seine JavaScript-Version JScript, was heute für ebensoviel Verwirrung sorgt.
Browserkrieg In der vierten Version der Browser hat JavaScript (und JScript)3 einen deutlichen Sprung gemacht. Die Objekt-Modelle der Browser wurden erweitert 1
2
3
32
Gegründet als Mosaic Communications von Jim Clark, der bereits mit Silicon Graphics ein erfolgreiches Unternehmen aus der Taufe gehoben hatte, und Marc Andreessen, einem Studenten in Stanfort, der den ersten grafischen Webbrowser Mosaic entwickelt hat. Aus Mosaic entstand auch der erste Netscape Navigator. Java ist zur gleichen Zeit von den Clients mehr und mehr verschwunden. Java-Applets finden sich im Web immer weniger. Dafür feiert Java in verschiedenen Formen serverseitig neue Erfolge. JavaScript schließt im Folgenden und im ganzen Buch JScript mit ein. Ist speziell von der Microsoft-Implementierung die Rede, dann wird es JScript genannt.
KOMPENDIUM
JavaScript
Historie
Kapitel 1
(siehe Kapitel 10 »Document Object Model«) und eine Vielzahl an Funktionen kamen hinzu. Das Problem war damals jedoch, dass beide Browser in vielen Bereichen völlig unterschiedliche Wege gingen. Erste Standardisierungsbemühungen der ECMA für JavaScript und des W3C (World Wide Web Consortium) für das Objekt-Modell (DOM = Document Object Model) waren zwar schon auf dem Weg, aber in der Hitze des Browsergefechts ging einiges unter. Diese Zeiten waren hart für JavaScript-Programmierer. Browserunterschiede waren noch wichtiger als heute. Aktuell kann man wenigstens auf eine Unterstützung der dritten Generation, also Internet Explorer 3 und Netscape Navigator 3, verzichten. Ähnlich hart wurde es für Netscape: Microsoft zog mit fairen und weniger fairen Mitteln am Wettbewerber vorbei und Netscape ging schließlich in AOL Time Warner auf.
Heute Der Browsermarkt im Jahr 2003 wird – vor allem unter Windows – deutlich von Microsofts Internet Explorer beherrscht. Die Marktanteils-Statistiken schwanken um die 90%, je nachdem welche Websites ihre Ergebnisse beisteuern. Neben dem Hauptbrowser bilden sich allerdings viele Nebenschauplätze. Nachdem Netscape seinen Quellcode freigegeben hatte, entwickelte sich daraus die Gecko-Engine und schließlich die neuen Netscape-Versionen 6 und 7 sowie Mozilla. Opera, schon lange eine gute Alternative auf dem Browsermarkt, macht in Version 7 einen Schwenk hin zu offiziellen Standards. Besonders beachtlich schlägt sich der Konqueror, ein Webbrowser unter Linux, der in die Benutzeroberfläche KDE integriert ist. Seine Engine KHTML wurde von Apple dazu ausersehen, die Grundlage des neuen Safari für Mac OS X zu bilden. Ein guter JavaScript-Programmierer sollte die Entwicklung bei den Browsern sehr genau beobachten und auf möglichst vielen Browsern testen. Dieses Buch hilft Ihnen mit vielen Tabellen über die Browserkompatibilität, auch für die »Exoten« zu entwickeln. Im Anhang A »Browser« finden Sie die einzelnen Browser noch einmal detaillierter vorgestellt. Außer den Entwicklungen im Browserbereich gibt es in JavaScript natürlich noch weitere Strömungen: Die nächste JavaScript-Version wird wohl wesentlich stärker objektorientiert sein, zumindest wenn man den aktuellen, aber noch sehr vorläufigen Plänen glauben darf.4 Ein endgültiger Termin für neue Standards steht allerdings nicht fest. 4
Siehe hierzu Anhang C »JavaScript 2.0 und die Zukunft«
KOMPENDIUM
JavaScript
33
Kapitel 1
Wissenswertes Neben der zunehmenden Bedeutung der »exotischen« Browser und der Objektorientierung sind JavaScript-Programmierer einer weiteren Strömung ausgesetzt: dem Zeitgeist. Was ist gerade »in« im Web, welche Effekte gefallen, wie viel Usability muss sein (natürlich immer so viel wie möglich) und was verbessert den Komfort für den Nutzer? Dazu gibt es eigentlich nur zwei gute Ratschläge: Surfen Sie viel und denken Sie sich in Ihre Zielgruppe hinein.
1.2
ECMAScript
ECMAScript ist nicht gleich JavaScript. ECMAScript definiert einen großen Teil des Sprachkerns von JavaScript und damit auch von JScript. JavaScript erweitert diesen Sprachschatz allerdings um einige Funktionen und Möglichkeiten. Sie finden den ECMAScript-Standard unter http://www.ecma-international. org/publications/standards/ECMA-262.htm.
Leider kann die Skriptsprache selbst noch nicht mit der Webseite und den HTML-Inhalten darin kommunizieren. Dazu benötigt JavaScript das Object Model des Browsers. Die Standardisierung dieses Modells (DOM) obliegt dem W3C.5 Das Modell liefert die Browserobjekte, die den Zugriff auf die Elemente einer Webseite, wie beispielsweise Bilder, Links oder Formularelemente erlauben. Die folgende Tabelle gibt eine Übersicht über die Parallelen zwischen dem ECMAScript-Standard und den JavaScript- bzw. JScript-Versionen. Tabelle 1.1: JavaScript und ECMAScript
JavaScript-Version
JScript-Version
ECMAScript
1.0
1.0
1.1
1.1
1.2
3.0a
v1 (eingeschränkt)
1.3
5.0
v1
5.5 5.6
v3
1.4b 1.5
a. Den Zwischenschritt JScript 4.0 hat Microsoft ausgelassen. b. Nur in Netscape-Webservern, aber in keinem Browser implementiert.
5
34
Siehe Kapitel 10 »Document Object Model«
KOMPENDIUM
JavaScript
Weitere Einsatzgebiete
Kapitel 1
In Kapitel 2.4, Abschnitt »JavaScript-Versionen« finden Sie weitere Informationen zu den Browsern und den JavaScript-Versionen.
1.3
Weitere Einsatzgebiete
Das Haupteinsatzgebiet von JavaScript liegt eindeutig im Browser und damit in der clientseitigen Verwendung. Allerdings ist JavaScript oder der übergeordnete Standard ECMAScript entgegen der landläufigen Meinung auch in anderen Bereichen anzutreffen: Serverseitig in ASP (Active Server Pages), einer serverseitigen Technologie von Microsoft. ASP hinkt allerdings, was den Marktanteil betrifft, deutlich hinter dem Marktführer PHP her. Für den Entwickler bietet der Nachfolger ASP.NET mehr. Serverseitig in ASP.NET, dem Nachfolger von ASP. Hier heißt JavaScript JScript .NET. Eine Einführung in das .NET-Konzept und in JScript .NET finden Sie in Kapitel 24 »JScript .NET«. Die Diskussion, welche Aufgaben besser clientseitig und welche besser serverseitig erledigt werden, finden Sie in diesem Buch noch häufiger. Nicht behandelt wird die Frage, welche serverseitige Technologie die beste ist. Hier spielen viele Faktoren eine Rolle. Die Grabenkämpfe – gerade zwischen Microsoft und der Open-Source-Gemeinde rund um PHP – sind eine teilweise sehr emotionale Diskussion. Dieses Buch greift auf JScript .NET zurück, weil sich damit zwei Fliegen mit einer Klappe schlagen lassen: Eine (neue) serverseitige Technologie wird vorgestellt und sie lässt sich mit einer JavaScript-Variante programmieren. Als Skript-Sprache für neue Technologien wie beispielsweise SVG (Scalable Vector Graphics), einem Vektorgrafik-Standard des Internet-Standardisierungsgremiums W3C.6 Flash von Macromedia, der Quasi-Standard und Platzhirsch bei Vektorgrafiken und -animationen, verwendet eine Skriptsprache namens ActionScript. Sie ist – wie JavaScript – seit Flash 5 ein Abkömmling von ECMAScript. Wer das eine beherrscht, kann auch das andere lernen.
6
Siehe http://www.w3.org/Graphics/SVG
KOMPENDIUM
JavaScript
35
Kapitel 1
Wissenswertes
1.4
JavaScript und Sicherheit
Einige Dinge kann clientseitiges JavaScript nicht: beliebig Browserfenster schließen Netzwerk-Verbindungen herstellen oder verarbeiten Dateien öffnen und speichern Grafiken zeichnen.7 Der Grund für diese »Mängel« ist die Sicherheit. Niemand will einem Skript in einer fremden HTML-Seite das Recht geben, Dateien zu löschen. Diese strengen Sicherheitsregeln führen dazu, dass JavaScript verhältnismäßig wenig negative Schlagzeilen produziert. Die meisten Sicherheitslücken für den Internet Explorer wurden von ActiveX und damit VBScript gemeldet. Auch in Netscape gab es in den älteren Versionen 2 und 3 einige Probleme. Mehr über die Sicherheitsvorkehrungen von JavaScript erfahren Sie in Kapitel 22 »JavaScript und Sicherheit«.
7
36
Eine Ausnahme ist das dynamische Generieren von HTML-Elementen.
KOMPENDIUM
JavaScript
2
JavaScript in HTML
Clientseitiges JavaScript – das den größten Raum in diesem Buch einnimmt – erweitert HTML. Dementsprechend sind die JavaScript-Skripten auch Teil der HTML-Seite. Sie sind im normalen HTML-Code eingebunden und werden vom Server auf den Client übertragen und dort ausgeführt.
2.1
Einbau
Damit der Browser erkennt, dass es sich um JavaScript und nicht um HTML handelt, müssen die JavaScript-Bereiche innerhalb einer HTMLSeite hervorgehoben sein. So sieht ein normales HTML-Grundgerüst ohne JavaScript aus: HTML-Grundgerüst
Listing 2.1: Das HTML-Grundgerüst (grundgeruest.html)
In diesem Buch kommt recht viel HTML vor. Sie sollten also mit HTML in Grundzügen vertraut sein. Die Beispiele sind – soweit möglich und sinnvoll – XHTML-konform1: Alle Tags sind Kleinbuchstaben. Jedes Tag wird beendet, auch Tags ohne Ende-Tag:
statt:
1
zu finden unter: http://www.w3.org/TR/xhtml1/
KOMPENDIUM
JavaScript
37
Kapitel 2
JavaScript in HTML Attribute sind in Kleinbuchstaben geschrieben. Attribut-Werte stehen immer in Anführungszeichen. JavaScript-Skripten werden in HTML mit <script> und eingebunden. Zwischen diesen Tags steht der JavaScript-Code. Da die <script>-Tags auch von anderen Skriptsprachen verwendet werden, muss mit dem Attribut language die Sprache identifiziert werden. <script language="JavaScript">
Wenn Sie das language-Attribut weglassen, verwenden die aktuellen Browser dennoch JavaScript als Standard. Da dies allerdings nicht selbstverständlich ist, sollten Sie sich nicht darauf verlassen. Das <script>-Element findet seinen Platz im Kopf der HTML-Seite: Listing 2.2: Skript-Container im Kopf der HTMLSeite (script.html)
Der Skript-Container <script language="JavaScript"> document.write("Herzlich willkommen!");
Abbildung 2.1: Das Skript gibt einen Text aus.
Der Befehl document.write() gibt einen Text aus, der in Anführungszeichen innerhalb der runden Klammern steht. Eng verwandt ist document.writeln(), das eine einzelne Zeile ausgibt.
Alte Browser und deaktiviertes JavaScript Browser ohne JavaScript-Unterstützung sind ein ständig wiederkehrendes Problem für JavaScript-Programmierer. Prinzipiell lassen sich zwei Fälle unterscheiden:
38
KOMPENDIUM
JavaScript
Einbau
Kapitel 2
Browser, in denen JavaScript deaktiviert wurde. Sie ignorieren den Code in den <script>-Tags (siehe Abbildung 2.2). Die verschiedenen Browser und ihre Möglichkeiten, JavaScript zu deaktivieren, finden Sie im Anhang A »Browser«.
Abbildung 2.2: Mit deaktivierter JavaScript-Unterstützung zeigt ein JavaScript-fähiger Browser nichts an.
Alte Browser, die kein JavaScript unterstützen, kennen <script>-Tags nicht. Daher ignorieren sie die Tags und geben den Inhalt aus. Hier kann es also passieren, dass das ganze Skript in Klarsicht ausgegeben wird. Der erste Fall – deaktivierte JavaScript-Unterstützung – lässt sich nur dadurch umgehen, dass Ihre Website auch ohne JavaScript navigierbar ist. Im zweiten Fall müssen Sie auf jeden Fall verhindern, dass das Skript ausgegeben wird. Dazu gibt es einen Trick: Der ganze Skriptteil wird in HTMLKommentare eingeschlossen. Damit JavaScript nicht über das schließende Kommentarzeichen --> stolpert, steht davor ein JavaScriptKommentarzeichen // für einen einzeiligen Kommentar. Das folgende Beispiel illustriert diese Methode: Alte Browser <script language="JavaScript">
KOMPENDIUM
JavaScript
Listing 2.3: Kommentare verhindern Fehler in alten Browsern (alte_browser.html).
39
Kapitel 2
JavaScript in HTML Die folgenden Beispiele in diesem Buch enthalten die Kommentare standardmäßig. <noscript> Es gibt auch neuere Browser, die kein JavaScript unterstützen, beispielsweise die auf mobilen Endgeräten wie PDAs. Für diese Browser können Sie einen <noscript>-Container angeben. Dieser <noscript>-Container wird auch von Browsern mit deaktiviertem JavaScript ausgewertet und ausgegeben (siehe Abbildung 2.3).
Listing 2.4: Der <noscript>Container (noscript.html)
noscript <script language="JavaScript"> <noscript> Ihr Browser kann kein JavaScript
Abbildung 2.3: Der Navigator 7 gibt den Inhalt des <noscript>Containers aus, da die JavaScriptUnterstützung deaktiviert ist.
Abbildung 2.4: Mit aktiviertem JavaScript ignoriert der Navigator den <noscript>Container.
40
KOMPENDIUM
JavaScript
Einbau
Kapitel 2
Den <noscript>-Container finden Sie nicht in den Beispielen dieses Buches, da er den Code unnötig aufblähen würde.
Position des Skript-Bereichs Die Position des <script>-Containers sollte ursprünglich auf den Kopfbereich der HTML-Seite beschränkt bleiben. Bald aber wurde klar, dass insbesondere bei der Ausgabe von Text und Informationen ein <script>-Bereich im Körper an der Stelle sinnvoll ist, an der die Ausgabe erfolgen soll. Skript im Body
Herzlich willkommen ohne JavaScript
Listing 2.5: Skript im Körper der HTML-Seite (script_body.html)
<script language="JavaScript">
Wo ein Skript-Container, ist ein zweiter auch nicht weit. Vor allem die Kombination aus einem Skript-Container im Kopf und im Körper ist sehr sinnvoll. Im Kopf können beispielsweise Funktionen2 definiert sein, die dann im Körper aufgerufen werden. Skript in Head und Body <script language="JavaScript">
Listing 2.6: Skript in Kopf und Körper der HTML-Seite (script_beide.html)
<script language="JavaScript">
Eine dritte Möglichkeit besteht darin, zwei oder mehr Skripten im Kopf oder im Körper der HTML-Seite zu notieren. Zahl und Positionierung unterliegen hier also keiner Grenze:
2
Funktionen sind Code-Anweisungen, die jederzeit mit einem Namen aufgerufen werden können (siehe Kapitel 5 »Funktionen«).
KOMPENDIUM
JavaScript
41
Kapitel 2
JavaScript in HTML
Abbildung 2.5: Zuerst erfolgt die Ausführung des Skripts im Kopf und dann im Körper.
Listing 2.7: Zwei Skripten im Körper der HTML-Seite (script_beide_body. html)
Zwei Skripten im Body <script language="JavaScript">
Hallo von HTML
<script language="JavaScript">
Abbildung 2.6: Zuerst eine JavaScript-Ausgabe, dann eine HTMLAusgabe und anschließend wieder JavaScript
Moderne Browser kommen auch mit einem Skript-Bereich zwischen Kopf und Körper der HTML-Seite zurecht. Allerdings sollten Sie dies der Ordnung halber vermeiden.
42
KOMPENDIUM
JavaScript
Einbau
Kapitel 2
Kurzform Der Skript-Container war in unseren Beispielen immer relativ lang. Eine Zeile reicht allerdings auch aus (hier ohne language-Attribut): <script>document.write("Hallo");
Im Allgemeinen sollten Sie derartige Kurzformen meiden, da der Code dadurch unübersichtlicher wird und die HTML-Kommentare für alte Browser bei Kurzformen außen vor bleiben.
Externes JavaScript Bis jetzt war der JavaScript-Code immer Teil der HTML-Seite. Er lässt sich aber auch in einer eigenen Datei speichern. Eine Datei mit JavaScript-Code hat im Allgemeinen die Dateiendung .js. Im externen Skript werden nur die JavaScript-Befehle notiert: document.write("Herzlich willkommen!");
Der Aufruf des externen Skripts erfolgt mit dem Attribut src3 im <script>Tag:
Soll das externe Skript extern.js, das im gleichen Verzeichnis wie die HTML-Datei liegt, eingebunden werden, sieht die entsprechende Webseite wie folgt aus: Externes Skript einbinden <script src="extern.js" language="JavaScript">
Listing 2.9: Ein externes Skript einfügen (skript_extern.html)
3
Der Verweis auf das externe JavaScript kann relativ (z.B. .../skripte/extern.js) oder absolut (http://www.mut.de/skripte/extern.js) erfolgen.
KOMPENDIUM
JavaScript
43
Kapitel 2
JavaScript in HTML
Abbildung 2.7: Die Ausgabe mit dem externen Skript funktioniert.
Sie sehen im Skript noch eine Anweisung innerhalb des <script>-Containers. Alle Browser, die mindestens JavaScript 1.1 beherrschen – das sind alle neueren Browser ab Netscape 3 und Internet Explorer 3 in der zweiten Version – ignorieren die Anweisung im Skript-Container, wenn das src-Attribut vorhanden ist. Die früheren Browserversionen, also hauptsächlich Netscape 2, konnten mit externen Skripten noch nichts anfangen. Sie führen nur die Anweisungen im Skript-Container aus. Abbildung 2.8: Netscape 2 führt die Anweisung im <script>-Container aus, da er mit dem externen Skript nichts anfangen kann.
Die Verwendung von externen Skripten hat einige Vorteile: Externe Skripten sind an zentraler Stelle verwaltbar. Jede Webseite kann auf ein externes Skript zugreifen. Häufig verwendete Funktionen (siehe Kapitel 5 »Funktionen«) können dort also ausgelagert werden. Ein Zugriff ist von jeder Webseite aus möglich. Externe Skripten sind nicht ganz so einfach aus dem Quelltext zu kopieren, wie JavaScript-Code direkt in der Webseite. Externe Skripten müssen nicht von demselben Webserver aufgerufen werden. Sie können auch mit einem absoluten Link auf ein Skript eines anderen Webservers verweisen.
44
KOMPENDIUM
JavaScript
Einbau
Kapitel 2
Die Nachteile sollen allerdings auch nicht verschwiegen werden: Beim Zugriff auf ein externes Skript muss eine Verbindung über das Internet (oder Intranet) aufgebaut werden. Das kostet Performance. Der Verlust gleicht sich aus, wenn mehrere Webseiten auf dasselbe Skript zugreifen, da der Browser es in den Cache übernimmt. Beim Programmieren müssen immer zwei Dateien kontrolliert werden. Dies macht sich negativ bemerkbar, wenn der JavaScript-Code häufig auf HTML-Elemente der Webseite zugreift. In Uraltbrowsern wie dem Netscape Navigator 2 und dem Internet Explorer vor 3.02 funktionieren externe JavaScript-Dateien gar nicht. Für den Internet-Explorer 3.02 und 3.03 muss der MIME-Typ des Webservers für Dateien mit js-Endung auf APPLICATION/X-JAVASCRIPT gesetzt sein. Als Fazit lässt sich ziehen, dass häufig und von mehreren Webseiten benötigte Funktionen in externe Skripten ausgelagert werden sollten. Seitenspezifische Anwendungen wie Ausgaben, Formularüberprüfungen usw. dagegen besser direkt in der Webseite aufgehoben sind. Speichern Sie wichtige Funktionen in externen Skripten und verwenden Sie für seitenspezifische Aufgaben einen zweiten Skript-Container in der Webseite. In diesem Buch finden Sie Skripten hauptsächlich direkt in der Webseite. Das drückt keine Vorliebe des Autors aus. Der Grund dafür ist, dass Webseite und Skript nicht in zwei Listings abgedruckt werden müssen. Durch die Hervorhebungen bleibt das Geschehen im Skript dennoch immer übersichtlich.
MIME-Type Das language-Attribut ist dem W3C-Standardisierungsgremium von HTML 4.014 nicht gut genug. Das Problem besteht darin, dass die Liste der Sprachen, die für das language-Attribut zugelassen sind, nicht festgeschrieben ist. Daher wird angeraten, die Identifikation über den so genannten MIMEType (Multipurpose Internet Mail Extensions) vorzunehmen. Für den MIME-Type wird das HTML-Attribut type verwendet. Für JavaScript sieht die Identifikation so aus: <script type="text/javascript">
4
zu finden unter http://www.w3.org/TR/html4/
KOMPENDIUM
JavaScript
45
Kapitel 2
JavaScript in HTML Die Standards zum MIME-Type werden von der IETF (Internet Engineering Task Force) verwaltet. Die beiden relevanten Dokumente sind RFC2045 (http://www.ietf.org/rfc/rfc2045.txt) und RFC2046 (http:// www.ietf.org/rfc/rfc2046.txt). Da das language-Attribut bisher jedoch weiter verbreitet ist, wird es auch in diesem Buch eingesetzt. Wollen Sie jedoch auch den MIME-Type unterbringen und verwenden Sie nur eine Skriptsprache in einer Webseite (was meist der Fall ist), können Sie auch ein <meta>-Tag in den Kopf der HTML-Seite schreiben: <meta http-equiv="Content-Script-Type" content="text/javascript">
In diesem Fall können Sie language- oder type sogar weglassen. Sinnvoller ist es allerdings, dennoch das language-Attribut zu verwenden, falls ein Browser-Exot mit dem <meta>-Tag für Content-Script-Type nichts anfangen kann.
2.2
JavaScript in Links
JavaScript-Code im <script>-Container wird beim Laden der Seite ausgeführt. Einzige Ausnahme ist Code innerhalb einer Funktion (siehe Kapitel 5 »Funktionen«). Eine Funktion enthält Anweisungen und kann jederzeit mit ihrem Namen aufgerufen werden. Das sofortige Ausführen von Code ist manchmal sinnvoll. In vielen Fällen soll allerdings auf Nutzereingaben gewartet werden. Eine Methode besteht darin, JavaScript-Code in einen Link zu schreiben5. Dafür wird im hrefAttribut statt eines der normalen Protokolle – beispielsweise http: für absolute Links auf Webseiten oder mailto: für E-Mail-Links – javascript: verwendet. Dahinter dürfen ganz normale JavaScript-Anweisungen stehen. Linktext
Im folgenden Beispiel gibt der Link per JavaScript einen Text aus: Listing 2.10: Ein JavaScript-Link (javascript_link.html)
Hier wird der Event-Handler immer zuerst ausgeführt (siehe Abbildung 2.10). Wenn im JavaScript-Code nicht bereits eine Weiterleitung aktiviert ist, kommt allerdings der Link zum Tragen. Abbildung 2.10: Beim Anklicken des Links erscheint das Fenster mit der Warnmeldung.
Wollen Sie die Weiterleitung auf jeden Fall verhindern und auf derselben Webseite bleiben, sollte das href-Attribut nur ein Doppelkreuz7 (#) enthalten. Das Doppelkreuz ist das Symbol für einen HTML-Anker. Folgt dahinter kein Ankername, wird die Seite mit dem Link aufgerufen: Bitte klicken
7
48
auch Hash oder Raute
KOMPENDIUM
JavaScript
Versionsunterscheidung
Kapitel 2
Dieser Trick wird in der Praxis sehr häufig verwendet, da so zum einen in älteren Browsern keine Fehlermeldung erscheint, wie bei JavaScript-Links, zum anderen aber auch nicht auf eine andere Seite gesprungen wird. Allerdings scrollt der Browser häufig an den Anfang der Seite, was bei längeren Seiten unpraktisch ist. Event-Handler können in HTML beliebig mit Groß- und Kleinbuchstaben geschrieben werden, da HTML und damit auch HTML-Attribute nicht zwischen Groß- und Kleinschreibung unterscheiden8. JavaScript dagegen erlaubt Event-Handler im JavaScript-Code nur in Kleinbuchstaben. Zur Groß- und Kleinschreibung in JavaScript siehe auch Kapitel 3.3 im Abschnitt »Groß- und Kleinschreibung«. Wichtige Event-Handler An dieser Stelle lernen Sie bereits einige Event-Handler kennen: onclick – ist ein Mausklick auf ein Objekt. onmouseover – der Mauszeiger fährt auf ein Objekt. onmouseout – der Mauszeiger verlässt das Objekt wieder. onchange – ein Formularfeld oder Objekt ändert sich. onload – wenn die Webseite geladen ist. Dieses Attribut ist meist Teil des -Tags. onunload – wenn der Nutzer die Webseite verlässt. onunload befindet sich auch meist im -Tag.
Ausführlichere Informationen zum Thema erhalten Sie in Kapitel 11 »Ereignisse und Event-Handler«.
2.4
Versionsunterscheidung
Das language-Attribut des <script>-Tags bietet noch eine Überraschung: Es erlaubt die Angabe der JavaScript-Version: <script language="JavaScript1.3">
Obige Zeile wird nur in Browsern ausgeführt, die JavaScript 1.3 oder höher unterstützen.
8
Die Unterscheidung zwischen Groß- und Kleinschreibung heißt auch case-sensitiv.
KOMPENDIUM
JavaScript
49
Kapitel 2
JavaScript in HTML Beachten Sie, dass zwischen dem Sprachnamen und der Versionsnummer im language-Attribut kein Leerzeichen steht.
JavaScript-Versionen Die Zuordnung anhand der JavaScript-Versionen ist – wie sollte es anders sein – nicht völlig trivial. Vor allem die beiden großen Browser Internet Explorer und Netscape Navigator bereiten einige Schwierigkeiten. Die folgenden Tabellen verschaffen einen Überblick darüber, welcher Browser welche JavaScript-Versionen unterstützt. Behalten Sie die Versionen im Hinterkopf, denn sie hilft beim Programmieren von Plattform-übergreifenden Skripten. Tabelle 2.1: JavaScriptVersionen und der Microsoft Internet Explorer
JavaScript-Version JScript-Version ab Internet Explorer-Version 1.0
1.0
3
1.1
1.1
3, zweite Versiona
1.2
3.0b
4.0
1.3
5.0
5.0
1.4 1.5
in keinem Browser vorhanden 5.5
5.5 (nur teilweise ECMA v3-kompatibel)
5.6
6.0 (ECMA v3-kompatibel)
a.
Der Internet Explorer 3.0 ist in zwei Versionen erschienen: die erste mit JavaScript 1.0 und die zweite mit JavaScript 1.1. b. Den Zwischenschritt JScript 4.0 hat Microsoft ausgelassen. Tabelle 2.2: JavaScriptVersionen und Netscape Navigator
50
JavaScript-Version
ab Netscape Navigator-Version
1.0
2.0
1.1
3.0
1.2
4.0 bis 4.05
1.3
4.06 bis 4.8
1.4
in keinem Browser vorhanden
1.5
6.0 und 7.0
KOMPENDIUM
JavaScript
Versionsunterscheidung
Kapitel 2
Besondere Schwierigkeiten macht die JavaScript-Version 1.2 im Netscape Navigator. Netscape hatte hier bereits einige Funktionalitäten übernommen, die zur Standardisierung durch die ECMA vorgeschlagen waren. Leider wurden sie nicht genommen und daher ist JavaScript 1.2 im Netscape Navigator teilweise inkompatibel zu JavaScript 1.2 im Internet Explorer und zu JavaScript in späteren Netscape-Versionen. Dies erklärt auch den frühen Wechsel von Netscape auf JavaScript 1.3 (bereits in Version 4.0.6). Hier lautet die Empfehlung, als language-Attribut nicht JavaScript1.2 zu verwenden. JavaScript-Version
ab Browserversion
1.5
Mozilla 1.0
1.3
Konqueror 3.0
1.3
Opera 6.0a
1.5
Opera 7.0
a.
Tabelle 2.3: JavaScript und die alternativen Browser
Einschränkungen: http://www.opera.com/docs/specs/
Mehr zu den Browsern und ihrer Geschichte erfahren Sie im Anhang A »Browser«. Da die vorhergehenden Tabellen nur einen groben Überblick liefern können und es für (fast) jeden Browser Einschränkungen und Probleme gibt, finden Sie im Verlauf dieses Buches für alle Sprachelemente und -objekte, die nicht problemlos in allen Browsern laufen, jeweils eine eigene Tabelle mit den Kompatibilitäten.
Browserunterscheidung Das language-Attribut mit Versionsnummer lässt sich auch einsetzen, um die JavaScript-Version in verschiedenen Browsern zu unterscheiden. Verwenden Sie beispielsweise das neue Fehler-Handling-Konzept von JavaScript 1.5 (siehe Kapitel 9 »Debugging«), packen Sie es in einen JavaScript-1.5-SkriptBlock, damit Browser ohne die Version 1.5 die Anweisungen ignorieren. Das folgende Skript gibt die – vom Browser unterstützten – JavaScript-Versionen aus: Welche Version?
Listing 2.12: Browserunterscheidung mit Sprachversionen (script_version.html)
<script language="JavaScript1.0">"); //-->
KOMPENDIUM
JavaScript
51
Kapitel 2
JavaScript in HTML <script language="JavaScript1.1">"); //--> <script language="JavaScript1.2">"); //--> <script language="JavaScript1.3">"); //--> <script language="JavaScript1.4">"); //--> <script language="JavaScript1.5">"); //-->
Die Ausgabe im Internet Explorer (siehe Abbildung 2.11) erstaunt ein wenig. Er unterstützt nur JavaScript bis Version 1.3. In Tabelle 2.1 wird ihm allerdings 1.5 nachgesagt. Was den Befehlsumfang betrifft, hat die Tabelle recht, allerdings behandelt Microsoft hier das language-Attribut sehr vorsichtig. Wenn Sie also wünschen, dass JavaScript-Code im IE 6 ausgeführt wird, müssen Sie als höchste Version JavaScript 1.3 angeben. Abbildung 2.11: Der Internet Explorer 6 behauptet von sich, er unterstütze kein JavaScript 1.4 und 1.5.
Abbildung 2.12: Netscape 7 kann alles.
52
KOMPENDIUM
JavaScript
Besonderheiten
2.5
Kapitel 2
Besonderheiten
Zum Abschluss dieses Kapitels folgen noch einige Besonderheiten des <script>-Tags. Sie sind entweder Browser-spezifisch oder weniger weit verbreitet.
<script for> Im Internet Explorer ab Version 4.0 führt das <script>-Tag mit einem forAttribut JavaScript-Code beispielsweise für Formularelemente aus. Das Ereignis, bei dem der Code ausgeführt wird, steht im event-Attribut. Das for-Attribut verwendet das name-Attribut, um das HTML-Element anzusprechen. Daher sollten Sie keinen Namen zweimal vergeben. Ist dies jedoch der Fall, wird der JavaScript-Code bei beiden Objekten ausgeführt. <script for="Elementname" event="Ereignis" language="JavaScript">
Die Ereignisnamen sind dieselben, wie bei den Event-Handlern. Da es sich hier allerdings um den Event-Handler als JavaScript-Code handelt, müssen die Ereignisse komplett in Kleinbuchstaben geschrieben werden. script for <script for="feld" event="onchange" language="JavaScript">
Listing 2.13: Mit <script for> auf ein Ereignis reagieren (script_for.html)
Browser, die <script for> nicht unterstützen, führen den kompletten JavaScript-Codeblock sofort beim Laden der Seite aus.
<script defer> Das Attribut defer dient dem <script>-Tag zur Performance-Steigerung. Es gibt dem Browser an, dass der JavaScript-Codeblock keine Elemente enthält, die auf der Seite ausgegeben werden sollen. Das bedeutet in den meisten Fällen, dass es sich um Code mit Funktionen handelt. Der PerformanceVorteil resultiert daraus, dass der Browser zuerst die HTML-Seite rendert und sich erst dann um den Skript-Block kümmert.
KOMPENDIUM
JavaScript
53
Kapitel 2
JavaScript in HTML
Abbildung 2.13: Bei geänderter Eingabe gibt der Internet Explorer einen Text aus.
Abbildung 2.14: Der Navigator führt den Codeblock sofort aus.
Das folgende Beispiel demonstriert den Einsatz von defer: Listing 2.14: Der Einsatz von defer (defer.html)
defer <script defer language="JavaScript">
<script language="JavaScript">
54
KOMPENDIUM
JavaScript
Besonderheiten
Kapitel 2
Zuerst wird die Variable x definiert. Da sie aber in einem Skript-Block mit defer steht, führt der JavaScript-Interpreter des Internet Explorers diese Deklaration zum Schluss aus. Das heißt, im zweiten Skript-Block steht x noch nicht zur Verfügung. Der Internet Explorer 6 liefert daher eine Fehlermeldung (siehe Abbildung 2.15). Abbildung 2.15: Der Internet Explorer 6 bemängelt, dass x noch nicht definiert wurde.
Der Netscape Navigator kennt defer nicht. Daher werden die Skript-Blöcke alle normal verarbeitet und die Ausgabe erfolgt wie erwartet (siehe Abbildung 2.16). Abbildung 2.16: Im Netscape erscheint das richtige Ergebnis, da defer unbekannt ist.
Im Allgemeinen sollten Sie defer nicht einsetzen. Auch in Intranets, die nur auf dem Internet Explorer basieren, ist der Performance-Gewinn so gering, dass das »mutwillige« Ausschließen anderer Browser dafür nicht sinnvoll erscheint.
KOMPENDIUM
JavaScript
55
3
Syntax und Variablen
Am Anfang und im Zentrum der JavaScript-Programmierung stehen Daten und Werte, unabhängig davon, ob Sie nur einen einfachen Text ausgeben möchten oder komplexe Algorithmen schreiben. Es handelt sich immer darum, Werte zu behandeln und zu ändern. Daten werden in JavaScript – wie auch in anderen Programmiersprachen – in Variablen gespeichert, wenn sie weiterverwendet und verändert werden sollen. Daten, die direkt in Anweisungen geschrieben werden, nennt man dagegen Literale. Sie sind nicht veränderbar und treten nur einmal auf. Ein Literal ist beispielsweise der Text »Alles Gute!« in der folgenden Textausgabe: document.write("Alles Gute!");
In Kapitel 3.2 »Variablen deklarieren« zeigen wir Ihnen, wie Sie Variablen erzeugen und mit ihnen arbeiten.
3.1
Datentypen
Daten treten nicht einfach nur als Literale oder Variablen auf, sie unterscheiden sich auch aufgrund ihrer Art. Folgende Zeilen verdeutlichen das: document.write(4); document.write("Text");
Die erste Zeile gibt 4 aus. 4 ist eine ganze Zahl (Number). Die zweite Zeile dagegen enthält Text. Der zugehörige Datentyp heißt String und wird in JavaScript immer in Anführungszeichen geschrieben. Im Folgenden erhalten Sie eine Übersicht über alle Datentypen, die JavaScript unterscheidet.
KOMPENDIUM
JavaScript
57
Kapitel 3
Syntax und Variablen In Kapitel 3.3 im Abschnitt »Typkonvertierung« wird erklärt, wie JavaScript die verschiedenen Datentypen intern behandelt und wie Sie den Datentyp eines Wertes ändern.
Integer Integer sind ganze Zahlen ohne Nachkommastellen, die sowohl positive als auch negative Werte annehmen können, also beispielsweise: -1 20 0
Die einzige Frage ist, wie klein oder groß die Zahlen werden dürfen. JavaScript stellt Integer von -253 (-9 007 199 254 740 992) bis +253 (+9 007 199 254 740 992) exakt dar. Kleinere oder größere Zahlen können zwar verarbeitet werden, aber sie verlieren die exakten Endziffern. In folgender Zeile hängen wir einfach 67 an die kleinste darstellbare Zahl an. document.write(-900719925474099267);
Der Interpreter rundet die drei Endziffern: -900719925474099300
Bei einigen Anwendungen, vor allem den Bit-Operatoren, ist der mögliche Wertebereich kleiner. Er umfasst dann nur 32 Bit, geht also von -231 (-2 147 483 648) bis +231-1 (2 147 483 647). Die JavaScript-Funktion1 isFinite() testet, ob eine Zahl noch endlich, also kleiner bzw. größer als die größte bzw. kleinste speicherbare Zahl in JavaScript ist. Wenn dies der Fall ist, wird als Ergebnis der Wahrheitswert (Boolean) true zurückgeliefert. Beachten Sie, dass die größte bzw. kleinste speicherbare Zahl nichts mit der größten bzw. kleinsten exakt darstellbaren Zahl zu tun hat. Sie kann wesentlich größer bzw. kleiner sein, weist dann jedoch Ungenauigkeiten bei den letzten Stellen hinter dem Komma auf. Mehr zu inFinite() finden Sie in Kapitel 5.3 »Globale Funktionen«. Hexadezimale Schreibweise Integer können auch anders geschrieben werden. Eine recht bekannte Möglichkeit ist die hexadezimale Schreibweise. Das hexadezimale System hat nicht die Basis 10 – wie unsere Zahlenschreibweise –, sondern die Basis 16. 1
58
Eine Funktion ist ein Block aus einer oder mehreren Anweisungen, die mit ihrem Namen aufgerufen werden können. isFinite() gehört zu den Funktionen, die schon in JavaScript vorhanden sind. Mehr zu Funktionen erfahren Sie in Kapitel 5 »Funktionen«.
KOMPENDIUM
JavaScript
Datentypen
Kapitel 3
Das heißt, es gibt 16 Ziffern und da unsere Ziffern von 0 bis 9 nicht ausreichen, werden die Zahlen 10 bis 15 von den Buchstaben A bis F dargestellt. In JavaScript stellen Sie den hexadezimalen Ziffern 0x voran, um sie zu kennzeichnen, also beispielsweise: 0xAF
Die Umrechnung ist recht einfach: Die erste hexadezimale Ziffer A wird mit 16 multipliziert, dann wird die zweite F addiert. Für das angegebene Beispiel sieht die Rechnung wie folgt aus: 10 * 16 + 15 = 175
Diese Ausgabe können Sie auch im Browser überprüfen, da hexadezimale Werte automatisch umgerechnet werden: document.write(0xAF);
Das hexadezimale System wird vor allem in HTML dazu verwendet, RGBFarbwerte anzugeben. Für jeden der drei Farbkanäle bilden zwei hexadezimale Ziffern den jeweiligen Wert von 0 bis 255 ab. Die Reihenfolge ist dabei immer Rot, Grün und Blau. Folgender Farbwert entspricht dem RGB-Wert 255, 0, 0, der für reines Rot steht: #FF0000
Oktale Schreibweise Die oktale Schreibweise wird vom ECMA-262-Standard nicht unterstützt, aber von einigen JavaScript-Interpretern zugelassen. In Tabelle 1.1 finden Sie eine Übersicht, welcher aktuelle Browser diese Schreibweise unterstützt. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 3.1: Die oktale Schreibweise
In der oktalen Schreibweise beginnen Zahlen immer mit einer 0. Anschließend folgen Ziffern von 0 bis 7. Für die oktale Schreibweise werden also nur 8 Ziffern verwendet, da die Basis 8 ist (oktal ist der griechische Begriff für Acht). Die Umrechnung ist recht einfach: 0265
ergibt 2*64 + 6*8 + 5 = 181
KOMPENDIUM
JavaScript
59
Kapitel 3
Syntax und Variablen Da einige Browser die oktale Schreibweise nicht unterstützen, sollten Sie sie normalerweise vermeiden. Die Schwierigkeit besteht für die Browser darin, dass sie nicht erkennen, ob die vorangestellte 0 für einen Dezimalwert oder die oktale Schreibweise steht.
Gleitkommazahlen Gleitkommazahlen (Float) haben Nachkommastellen, die durch einen Dezimalpunkt abgetrennt werden. Der Punkt verdeutlicht, dass JavaScript aus dem anglophonen Sprachraum kommt. Dort ersetzt der Dezimalpunkt das bei uns bekannte Dezimalkomma. 4.65
Erscheint vor dem Punkt keine Zahl, ist die Zahl vor dem Komma eine 0: .848
steht also für 0,848. In JavaScript wird im Allgemeinen nicht zwischen Integern und Fließkommazahlen differenziert. Beide werden auch als Datentyp Zahl bezeichnet. Beachten Sie, wie schnell es geschehen kann, dass eine Gleitkommazahl auf einmal mit einem Komma statt einem Punkt im Skript landet. Der JavaScript-Interpreter ignoriert im Allgemeinen das Komma und gibt keinen Fehler aus, was die Fehlersuche sehr erschwert. Bei document.write() sind mehrere durch Kommata getrennte Parameter möglich. Die folgende Zeile document.write(0,40 + 4);
entspricht also document.write(0); document.write(40 + 4);
In Abbildung 3.1 sehen Sie, dass der Browser statt 4,4 als Ergebnis 044 anzeigt. Gleitkommazahlen nehmen Werte von 10-324 bis 10308 an. Größere Werte werden unendlich (Rückgabe: Infinity).
60
KOMPENDIUM
JavaScript
Datentypen
Kapitel 3 Abbildung 3.1: Der Browser zeigt aufgrund des Kommas ein falsches Ergebnis an.
Exponential-Schreibweise Neben der normalen Schreibweise existiert ebenfalls eine alternative Schreibweise mit Exponent. Zuerst folgt eine reelle Zahl, dann der Buchstabe E (oder e), ein Vorzeichen (Plus oder Minus) und eine ganze Zahl als Exponent. Wird das Vorzeichen weggelassen, nimmt der JavaScript-Interpreter automatisch einen positiven Wert an. 2.2E2
steht also für 2,2 * 102 = 220. Da das Ergebnis ein Integer ist, bildet die Exponential-Notation genau genommen sowohl eine Schreibweise für Gleitkommazahlen als auch für ganze Zahlen. Wenn Sie eine Zahl in Exponential-Schreibweise ausgeben, wandelt der JavaScript-Interpreter sie nur bis zu einer bestimmten Größe in die normale Schreibweise um. 9e+20
wird als 900 000 000 000 000 000 000 ausgegeben, 9e+21
nur als 9e+21. Im negativen Bereich werden nur Exponenten bis -6 als normale Zahlen ausgegeben; ab -7 erfolgt Exponential-Notation.
Zeichenketten Zeichenketten oder auch Strings2 enthalten Text, der allerdings durchaus auch aus Ziffern und anderen Zeichen bestehen kann. Sie erkennen einen String im Code immer an den Anführungszeichen. 2
Da der Begriff String aus Programmierersicht die richtige Bezeichnung für den Datentyp ist, verwenden wir im weiteren Verlauf des Buches hauptsächlich diesen Anglizismus. Taucht der Begriff Zeichenkette auf, ist dies als Synonym zu String zu verstehen.
KOMPENDIUM
JavaScript
61
Kapitel 3
Syntax und Variablen "Text"
Ebenfalls ein String ist: "12,30 Euro"
Die Anführungszeichen, die die Strings umgeben, können auch nur einfache Anführungszeichen sein: 'Text'
Der JavaScript-Interpreter erlaubt keine Mischung von einfachen und doppelten Anführungszeichen: document.write("Text');
zur Ausgabe eines Strings ist also verboten. Der Browser gibt einen Fehler aus (siehe Abbildung 3.2). Abbildung 3.2: Die Fehlermeldung im Internet Explorer 6, wenn die Anführungszeichen nicht korrekt angegeben wurden.
String-Länge Ein String darf in JavaScript eine unbegrenzte Länge haben. Allerdings sollten Sie den String nicht mit einem Zeilenumbruch im Texteditor zwischen den Anführungszeichen umbrechen, da dies zu einem Fehler führt. Einige sehr alte Browser unterstützen nur Strings mit maximal 255 Zeichen. Dies ist wichtig, wenn Sie eine 100%-Abwärtskompatibilität anstreben.
62
KOMPENDIUM
JavaScript
Datentypen
Kapitel 3
Escape-Sequenzen Wenn Sie in Strings Anführungszeichen oder Apostrophe (die geraden Anführungszeichen entsprechen) verwenden möchten, kann es Probleme geben. Folgender String ist problematisch: 'Ich denk's mir'
Der Interpreter nimmt an, das zweite gerade Anführungszeichen sei bereits das Ende des Strings. Um ihm zu signalisieren, dass das gerade Anführungszeichen keine JavaScript-Bedeutung hat, wird es mit einem Backslash (\)3 entwertet. 'Ich denk\'s mir'
Der Backslash ist das allgemein gültige Zeichen für die Entwertung von Zeichen. Den Backslash in Verbindung mit dem Zeichen nennt man EscapeSequenz (häufig auch Steuerelemente). In JavaScript gibt es einige standardmäßig verfügbare Escape-Sequenzen, die in Tabelle 3.2 aufgeführt sind. Wenn Sie ein Zeichen, das nicht entwertet werden müsste, mit dem Backslash (\) entwerten, hat dies keine Auswirkungen, da der Browser den Backslash einfach ignoriert. Wollen Sie dagegen einen Backslash in den Text einfügen, sollten Sie ihn als EscapeSequenz (\\) schreiben. EscapeSequenz
Beschreibung
\0
Nullzeichen; NUL. Alle Zeichen dahinter werden ignoriert. Das Nullzeichen terminiert den String.
\b
Backspace; entspricht der (Entf)-Taste, wird aber nicht von allen Browsern interpretiert.
\f
Seitenvorschub
\n
Zeilenumbruch; beachten Sie, dass dieser Zeilenumbruch nicht funktioniert, wenn Sie den String auf einer HTML-Seite ausgeben. Hier benötigen Sie das HTML-Tag .
\r
Wagenrücklauf; stammt noch aus der Schreibmaschinenzeit. Der Cursor geht bis an den Anfang auf das erste Zeichen in der nächsten Zeile zurück.
\t
Tabulator
3
Tabelle 3.2: Escape-Sequenzen von JavaScript
Tastenkürzel (AltGr) + (ß)
KOMPENDIUM
JavaScript
63
Kapitel 3 Tabelle 3.2: Escape-Sequenzen von JavaScript (Forts.)
Syntax und Variablen
EscapeSequenz
Beschreibung
\v
Vertikaler Tabulator; wird auch von neueren Browsern nicht unterstützt und ist daher zu meiden.
\\
Backslash; gibt einen Backslash aus.
\'
Einfaches Anführungszeichen
\"
Doppeltes Anführungszeichen
\xAA
Zeichen aus dem Latin-1-Zeichensatz, wobei die Zeichennummer durch den hexadezimalen Wert bei AA angegeben wird (Latin-1-Zeichen können auch in oktaler Schreibweise mit drei Ziffern angegeben werden. Dies wird von den neueren Browsern unterstützt, ist aber nicht Teil der ECMA-262 v3).
\uAAAA
Zeichen aus dem Unicode-Zeichensatz, wobei die Zeichennummer als hexadezimaler Wert mit vier Stellen (AAAA) angegeben wird (in Kapitel 3.3 unter »Zeichensatz« erfahren Sie Details zu den Zeichensätzen in JavaScript).
Die besonderen Escape-Sequenzen für den Zeilenumbruch, den Wagenrücklauf und den Tabulator sehen Sie in JavaScript am einfachsten in einem Warnfenster, das mit alert() erzeugt wird. Listing 3.1: Escape-Sequenzen im Einsatz (escape_ sequenzen.html)
Escape-Sequenzen <script language="JavaScript">
//--> Abbildung 3.3: Die EscapeSequenzen in einem Warnfenster
64
KOMPENDIUM
JavaScript
Datentypen
Kapitel 3
Bei einem Warnfenster oder ähnlichem entscheiden sowohl der Browser als auch das Betriebssystem, wie Escape-Sequenzen angezeigt werden. Entsprechend gibt es einige Unterschiede, vor allem beim Zeilenumbruch: Der Netscape Navigator unter Windows stellt beispielsweise den Wagenrücklauf nicht als Zeilenumbruch dar. Er benötigt ein \n. Testen Sie also gut! Abbildung 3.4: Der Wagenrücklauf wird nicht angezeigt.
Boolean Der Datentyp Boolean4 besteht nur aus zwei Zuständen: wahr oder falsch. Entsprechend heißt er auch Wahrheitswert. Wann benötigt man diesen Datentyp? Recht häufig, da in der Programmierung oftmals eine Bedingung überprüft wird, die dann wahr oder falsch zurückliefert. Ein Computer speichert Informationen in einem Bit. Dieses Bit kann ebenfalls nur zwei Zustände annehmen: 0 und 1. Entsprechend werden die beiden Wahrheitswerte manchmal auch als 0 (false = falsch) und 1 (true = wahr) geschrieben. JavaScript verwendet also entweder 0 für falsch und 1 für wahr oder alternativ die englischen Begriffe: true und false.5 var a = true; var b = false;
Im obigen Beispiel werden zwei Variablen definiert (siehe Kapitel 3.2 »Variablen deklarieren«). Variable a hat den Wert true und Variable b den Wert false.
4
5
Benannt ist der Datentyp nach dem englischen Mathematiker George Boole, geboren am 2. November 1815 in Lincoln, England und gestorben am 8. Dezember 1864 in Ballintempel, Irland. Er begründete die Boolesche Algebra, die Logik mit einfachen algebraischen Symbolen für die Mathematik greifbar machte. In den Beschreibungen finden Sie im Folgenden sehr oft die Anglizismen true und false, da sie in JavaScript die entsprechenden Schlüsselwörter für Wahrheitswerte darstellen.
KOMPENDIUM
JavaScript
65
Kapitel 3
Syntax und Variablen
Objekte Objekte – sowohl eingebaute als auch selbst definierte – sind für die Programmierung mit JavaScript sehr wichtig (siehe Kapitel 6 »Objekte«). Die komplexen Informationen, die in einem Objekt gespeichert werden, verlangen nach einem eigenen Datentyp: Object.6 Eigenschaften von Objekten, die Werte speichern, können einen beliebigen Datentyp, beispielsweise String oder Boolean annehmen.
Arrays Arrays speichern Datenelemente und vergeben einen Index, mit dem auf die Werte zugegriffen werden kann (siehe Kapitel 7 »Arrays und Strings«). Intern entspricht ein Array ebenfalls dem Datentyp Object.
Funktionen Funktionen stellen Anweisungen bereit, die von beliebiger Stelle aus dem Skript aufgerufen werden können (siehe Kapitel 5 »Funktionen«). Sie sind in JavaScript Daten des Typs Object.
Spezielle Werte Neben den einfachen (primitiven) Datentypen Zahl, String und Boolean und dem komplexen Datentyp Object, gibt es noch einige spezielle Werte. Das sind eigentlich Datentypen, die nur einen Wert haben. null Der Wert null steht für einen Datensatz ohne Wert. Er ist in JavaScript nicht gleichbedeutend mit 0, auch wenn er manchmal so verwendet wird. Sie erhalten beispielsweise 0, wenn Sie alle Elemente eines Arrays mit einer Schleife durchgehen (siehe Kapitel 7 »Arrays und Strings«) und das Ende des Arrays erreicht haben. Der nächste – nicht mehr vorhandene – Datensatz hat dann den Wert null. undefined Wenn eine Variable zwar deklariert ist, aber keinen Wert zugewiesen bekommen hat, hat sie den Wert undefined. Ebenso ist eine Objekteigenschaft ohne Wert undefined. Mit diesem Wert können Sie also prüfen, ob eine Variable oder Eigenschaft überhaupt einen Wert hat. 6
66
Der Datentyp Object wird auch als komplexer Datentyp bezeichnet. Einfache (oder primitive) Datentypen sind Zahl (Integer und Fließkomma), String und Boolean.
KOMPENDIUM
JavaScript
Variablen deklarieren
Kapitel 3
Der Vergleichsoperator7 für Gleichheit in JavaScript (==) setzt null und undefined gleich. Intern handelt es sich allerdings um unterschiedliche Werte. Dies wird mit dem Operator Genau gleich (===) sichtbar. Er berücksichtigt auch den Datentyp der zu vergleichenden Elemente und liefert bei einem Vergleich zwischen null und undefined das Ergebnis false. Infinity Infinity steht für unendlich. Dieser Wert wird ausgegeben, wenn eine Rechnung oder Zahl in JavaScript nicht mehr dargestellt werden kann. Sie ist dann unendlich.
NaN NaN besagt, dass ein Wert keine Zahl ist. Dies wird beispielsweise ausgegeben, wenn bei einer Berechnung nicht nur der Datentyp Zahl, sondern bei-
spielsweise ein String verwendet wird.
3.2
Variablen deklarieren
Um Variablen als Datenspeicher zu nutzen, müssen sie erst einmal erzeugt werden. Dieser Vorgang heißt Deklarieren. Der JavaScript-Interpreter erkennt an dem Schlüsselwort var, dass eine Variable deklariert werden soll: var x;
Diese Zeile deklariert die Variable x. Was geschieht beim Deklarieren? Der JavaScript-Interpreter erkennt, dass eine neue Variable angelegt werden soll. Er reserviert dann für die Variable Raum im Hauptspeicher und verknüpft diesen Platz mit dem Variablennamen, sodass er jederzeit darauf zugreifen kann, wenn die Variable wieder zum Einsatz kommt. In JavaScript müssen Sie bei der Deklaration der Variablen keinen der soeben besprochenen Datentypen zuweisen. JavaScript ist nicht typisiert, das heißt, eine JavaScript-Variable kann jeden Datentyp speichern, im Laufe ihrer Lebensdauer sogar unterschiedliche. Mehr dazu erfahren Sie in Kapitel 3.3 unter »Typkonvertierung«. Ist eine Variable erst einmal deklariert, kann Sie jederzeit mit ihrem Namen, in unserem Beispiel also x, aufgerufen werden. Ein einfacher Aufruf kann in der Ausgabeanweisung document.write() erfolgen: document.write(x); 7
Siehe Kapitel 4.1 »Operatoren«
KOMPENDIUM
JavaScript
67
Kapitel 3
Syntax und Variablen Da die Variable x bisher noch keinen Wert hat, wird undefined ausgegeben.
Abbildung 3.5: Bisher ist die Variable noch undefined.
Sie können auch mehrere Variablen in einer Zeile deklarieren. Trennen Sie die Variablen mit Kommata: var x, y;
definiert also x und y. Wenn Sie var weglassen, reserviert JavaScript für die Variable dennoch Platz im Hauptspeicher. Allerdings ist die Variable dann grundsätzlich global, das heißt im kompletten Skript verfügbar. Lokale Variablen sind auf eine Funktion beschränkt (siehe Kapitel 5.1 Abschnitt »Lokale und globale Variablen«). Wenn Sie eine lokale Variable in einer Funktion deklarieren wollen und var vergessen, kann es unter Umständen zu Problemen kommen, vor allem wenn das Skript noch gleichnamige globale Variablen besitzt.
Werte zuweisen undefined ist natürlich auf Dauer kein schöner Wert8 für eine Variable.
Daher muss sie einen Wert erhalten. Dies erledigt in JavaScript das IstGleich-Zeichen (=). var x = 3;
Diese Zeile weist der Variablen x den Wert 3 zu. Das Ist-Gleich heißt wegen seiner Funktion auch Zuweisungsoperator. Andere Operatoren finden Sie in Kapitel 4.1 »Operatoren«. Wird einer Variable, wie im aktuellen Beispiel, bereits beim Deklarieren ein Wert zugewiesen, spricht man auch von einer Initialisierung der Variablen. Abgesehen vom Sprachgebrauch kann eine Variable natürlich auch erst später einen Wert erhalten:
8
68
Der Wert einer Variable wird auch als Literal bezeichnet (siehe oben). Er tritt einmal auf. Ändert sich der Wert, handelt es sich um ein neues Literal.
KOMPENDIUM
JavaScript
Variablen deklarieren
Kapitel 3
var x; x = 3;
Diese Zeilen bewirken dasselbe wie die vorhergehende Initialisierung: Die Variable x erhält den Wert 3. Sollten Sie eine Variable häufiger mit dem Schlüsselwort var deklarieren, bleibt JavaScript gnädig. Wird bei der zweiten Deklaration ein Wert zugewiesen, übernimmt JavaScript den Wert als normale Zuweisung und ignoriert var. Erfolgt bei der ersten Deklaration eine Zuweisung, bei der zweiten dagegen nicht, behält die Variable den Wert aus der ersten Zuweisung. var x = 1; var x; document.write(x);
gibt also 1 aus.
Werte ändern Die Werte von Variablen sind beliebig änderbar. Um einer Variablen einen neuen Wert zuzuweisen, verwenden Sie einfach wieder den Zuweisungsoperator Ist-Gleich (=): var x = 3; x = 2;
Die Variable x erhält hier den Wert 3, der anschließend auf 2 geändert wird. Variablen sind aber noch mächtiger: Mit Berechnungen und Operatoren können Sie Variablen Rechnungsergebnisse zuweisen und sie miteinander verknüpfen. var x = 4 * 3; var y = x / 2;
Das Multiplikationszeichen (*) und das Divisionszeichen (/) sind so genannte arithmetische Operatoren. Sie und einige andere nützliche Operatoren lernen Sie in Kapitel 4.1 »Operatoren« kennen.
KOMPENDIUM
JavaScript
69
Kapitel 3
Syntax und Variablen
Strichpunkt (;) In den bisherigen Beispielen folgte nach jeder Variablendeklaration oder -zuweisung, aber auch nach jeder Ausgabe mit document.write() immer ein Strichpunkt (;)9. Der Strichpunkt beendet eine Anweisung in JavaScript. Muss er aber nicht. In anderen Sprachen, beispielsweise Java oder PHP, ist die Angabe des Strichpunkts Pflicht, der JavaScript-Interpreter dagegen meckert nicht, wenn Sie ihn weglassen. Die Beispiele in diesem Buch sind dennoch alle mit Strichpunkt ausgestattet.10 Dafür gibt es einen Grund: Anweisungen sehen wesentlich übersichtlicher aus, wenn sie beendet werden. Der Programmierstil wird sauberer. Wollen Sie mehrere Anweisungen in eine Zeile schreiben, müssen Sie diese durch Strichpunkte trennen: var x, y; x = 2; y = 4;
Fügen Sie keine Strichpunkte an, übernimmt das der JavaScript-Interpreter automatisch. Dies ist bei Anweisungen über mehrere Zeilen problematisch. Im Folgenden sehen Sie die Rückgabe eines Wertes in einer Funktion, über zwei Zeilen verteilt: return x;
Der Interpreter nimmt aber an, dass die obere Zeile eine eigenständige Anweisung ist und behandelt dies wie folgt: return; x;
Mit diesen Zeilen wird aber nicht x zurückgegeben, sondern die Funktion verlassen, ohne dass eine Rückgabe erfolgt. Die zweite Zeile x; wird ignoriert.
Mehrere Variablen Wenn Sie mehrere Variablen gleichzeitig, das heißt mit nur einem varSchlüsselwort, deklarieren wollen, trennen Sie sie durch Kommata: 9 Der Strichpunkt heißt auch Semikolon. 10 Wenn er hinter einer Anweisung fehlt, handelt es sich um ein Versehen des Autors. Eine kurze E-Mail an [email protected] genügt, und der Fehler wird in der nächsten Auflage behoben.
70
KOMPENDIUM
JavaScript
Bezeichner und Typen
Kapitel 3
var x, y, z;
definiert x, y und z als Variablen. Das funktioniert auch mit Wertzuweisung: var x = 2, y = 4, z = 5;
3.3
Bezeichner und Typen
Bevor Sie mit Variablen zu arbeiten beginnen und sich ans Programmieren machen, sollten Sie noch einige Grundlagen über Variablen und JavaScript mit auf den Weg nehmen. Dieses Kapitel behandelt hauptsächlich die Variablennamen (auch Bezeichner genannt) und die Typkonvertierung in JavaScript.
Groß- und Kleinschreibung JavaScript unterscheidet zwischen Groß- und Kleinschreibung11. Dies gilt nicht nur bei Variablennamen, sondern auch bei Funktionsnamen, JavaScript-Programmierelementen und Objekten. var Test = 3;
ist also eine andere Variable als test = 4;
Bei den Objekten gab es zeitweise Einschränkungen, was die Groß- und Kleinschreibung betrifft. Der Internet Explorer 3 hat in beiden Varianten bei Browserobjekten und -eigenschaften nicht auf Groß- und Kleinschreibung geachtet. Da dies in den späteren Versionen allerdings geändert wurde, hat das heute keine praktischen Auswirkungen mehr.
Variablennamen Ein Variablenname darf in JavaScript aus Buchstaben, Zahlen und dem Unterstrich (_) bestehen. Beginnen darf er allerdings nur mit einem Buchstaben oder dem Unterstrich, nicht aber mit einer Zahl. Darüber hinaus sind Sonderzeichen im Variablennamen nicht erlaubt.
11 Dies wird auch als case-sensitive bezeichnet.
KOMPENDIUM
JavaScript
71
Kapitel 3
Syntax und Variablen Folgende Namen sind korrekt: var _Hallo; var T_H_2; var x9302;
Nicht erlaubt sind dagegen: var Jo&Jo; var 90210; var 0acht;
Des Weiteren sind in Variablennamen die reservierten Schlüsselwörter von JavaScript verboten (siehe nächster Abschnitt) Was erlaubt ist, ist aber nicht unbedingt sinnvoll. Sie sollten sich angewöhnen, mit sprechenden Variablennamen oder einer schlüssigen Namenskonvention zu arbeiten. Besteht ein Variablenname aus mehreren Wörtern, trennen Sie ihn am besten mit Unterstrichen oder, indem Sie neue Wörter mit einem Großbuchstaben beginnen. var test_account; var testAccount;
Die zweite Variante gleicht auch der Konvention, die JavaScript bei seinen Methoden und Eigenschaften verwendet: Der Anfang – also das erste Wort – mit Kleinbuchstaben, neue Worte beginnen mit Großbuchstaben.
Reservierte Schlüsselwörter JavaScript verwendet – wie jede andere Programmiersprache auch – bestimmte Worte für Programmierkonstrukte. Beispielsweise gibt das Wort var dem JavaScript-Interpreter an, dass danach eine Variablendeklaration folgt. Diese Wörter heißen Schlüsselwörter. Sie sind reserviert, das heißt, Variablenbezeichner und jede andere Art von Bezeichner12 dürfen nicht so benannt werden. Die Vorgaben zu reservierten Schlüsselwörtern beginnen mit Wörtern, die bereits in der Sprache verwendet werden. Sie dürfen auf jeden Fall nicht als Bezeichner eingesetzt werden. Zusätzlich gibt es häufig für die Zukunft vorgesehene Schlüsselwörter, die oftmals noch als Bezeichner funktionieren würden. Wenn es dann aber neue Browserversionen gibt, versagen die alten Skripten mit diesen Bezeichnern. Daher gilt grundsätzlich die Regel, keine Schlüsselwörter als Bezeichner in Skripten zu verwenden. 12 beispielsweise Funktions- und Objektnamen
72
KOMPENDIUM
JavaScript
Bezeichner und Typen
Kapitel 3
Die grundlegenden Vorgaben für JavaScript kommen offiziell von der ECMA. In der Spezifikation ECMAScript-262 v3 werden die in Tabelle 3.3 und Tabelle 3.4 aufgeführten Schlüsselwörter reserviert. 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
abstract
enum
int
short
boolean
export
interface
static
byte
extends
long
super
char
final
native
synchronized
class
float
package
throws
const
goto
private
transient
debugger
implements
protected
volatile
double
import
public
Tabelle 3.3: Reservierte Schlüsselwörter von ECMAScript-262 v3
Tabelle 3.4: Für die Zukunft reservierte Schlüsselwörter von ECMAScript-262 v3
Netscape folgt in der JavaScript-Version 1.5 weitgehend den Vorgaben von ECMAScript-262 v3 (siehe Tabelle 3.5). abstract
Microsoft hat die JScript-Referenz auch an JScript.NET angepasst (läuft auch unter dem Namen JScript 7). Daher gibt es noch einige neue reservierte Schlüsselwörter. Diese sind zwar eigentlich nicht alle für den clientseitigen Einsatz vorgesehen. Aus Gründen der Kompatibilität zu zukünftigen Browsern und JavaScript-Implementationen sollten Sie sie allerdings dennoch nicht als Bezeichner verwenden. Tabelle 3.6: Die reservierten Schlüsselwörter in JScript (mit JScript.NET)14
Tabelle 3.7: Neue reservierte Wörter15
break
case
catch
class
const
continue
debugger
default
delete
do
else
export
extends
false
finally
for
function
if
import
in
instanceof
new
null
protected
return
super
switch
this
throw
true
try
typeof
var
while
with
abstract
boolean
byte
char
decimal
double
enum
final
float
get
implements
int
interface
internal
long
package
private
protected
public
sbyte
set
short
static
uint
ulong
ushort
void
14 Quelle: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/jscript7/html/jsreserved.asp 15 Wörter dürfen aufgrund der Abwärtskompatibilität als Bezeichner eingesetzt werden. Empfehlenswert ist dies allerdings nicht, da spätere Browserversionen dies eventuell untersagen.
74
KOMPENDIUM
JavaScript
Bezeichner und Typen
Kapitel 3
assert
ensure
event
goto
invariant
namespace
native
require
synchronized
throws
transient
use
volatile
Tabelle 3.8: Für die Zukunft reservierte Schlüsselwörter in JScript
Ein genauer Blick auf die Listen verrät, dass undefined bei Netscape und Microsofts JScript kein reserviertes Schlüsselwort ist, null dagegen schon16. Der Grund dafür ist, dass undefinied als globale Variable gesehen wird, deren Wert für alle Variablen und Eigenschaften ohne Wert gilt.
Formatierung JavaScript ignoriert Leerzeichen und Tabulatoren zwischen Ausdrücken (auch Token). Ein Ausdruck kann eine Variable, ein Programmierkonstrukt oder ein Bezeichner für ein Objekt sein. Leerzeichen und Tabulatoren in Ausdrücken werden natürlich nicht ignoriert, sondern teilen den Ausdruck in Mehrere. Für die Formatierung Ihrer Skripten sollten Sie also durchaus beispielsweise Leerzeichen verwenden. In diesem Buch werden die Zeilen für jede logische Skriptebene um jeweils zwei Leerzeichen eingerückt.
Zeichensatz Bisher haben Sie bereits die Beschränkungen bei Bezeichnern für Variablen, Funktionen und Objekte und die Verwendung von Escape-Sequenzen bei Strings kennen gelernt. Abgesehen von diesen Einschränkungen unterstützt JavaScript in neueren Browsern allerdings den kompletten Unicode-Zeichensatzes17. 18 NS4.x NS6
NS7
18
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 3.9: Unicode
16 außer in ECMAScript! 17 Unicode steht für Universal Code und vereinheitlicht und erweitert bestehende Zeichensätze. 18 ab Netscape Navigator 4.0.6
KOMPENDIUM
JavaScript
75
Kapitel 3
Syntax und Variablen Unterstützt der Browser kein Unicode, wird normalerweise automatisch nur der ASCII-Zeichensatz unterstützt. In ECMAScript ist Unicode erst in v3 allgemein gültiger Standard (außer in Bezeichnern). Vorher waren reine Unicode-Zeichen nur in Strings und Kommentaren (siehe Kapitel 3.4 unter »Kommentare«) zugelassen. Der Unicode-Zeichensatz hat eine Tiefe von 16 Bit und enthält die Zeichen für die meisten Sprachen der Welt. Ein Unicode-Zeichen wird wie folgt notiert: uAAAA AAAA steht dabei für die hexadezimale Zahl des Unicode-Zeichens.
Unter Windows 2000/XP ist die Zeichentabelle (START/PROGRAMME/ZUBEHÖR/SYSTEMPROGRAMME/ZEICHENTABELLE) sehr komfortabel geworden und zeigt von den Zeichen eines Zeichensatzes auch den Unicode an. Abbildung 3.6: Die Zeichentabelle unter Windows XP
76
KOMPENDIUM
JavaScript
Bezeichner und Typen
Kapitel 3
Typkonvertierung JavaScript konvertiert Datentypen von Variablen automatisch: var x = "drei"; x = 3;
Zuerst wird Variable x als Datentyp String initialisiert. Anschließend wird ihr ein Integer zugewiesen. Die Typkonvertierung von String in Zahl erfolgt automatisch. Die automatische Datentypkonvertierung unterscheidet JavaScript von anderen Programmiersprachen wie Java und C#, in denen der Datentyp für eine Variable explizit angegeben werden muss. Funktionen zur Typkonvertierung Benötigen Sie eine Zahl aus einem String für eine Berechnung oder möchten Sie einen anderen Datentyp in einen String umwandeln, müssen Sie Hilfsfunktionen verwenden. Diese Funktionen sind globale Funktionen, das heißt, sie stehen überall in JavaScript zur Verfügung: Element.toString()wandelt ein Element mit einem anderen Datentyp in
einen String um. Number(String) ändert einen String in eine Zahl und entscheidet automa-
tisch, ob das Ergebnis ein Integer oder eine Fließkommazahl ist. parseFloat(String) extrahiert eine Fließkommazahl aus einem String. parseInt(String) wandelt einen String in einen Integer um.
Wie die Funktionen zur Typkonvertierung arbeiten, erfahren Sie in Kapitel 5.3 im Abschnitt »Datentypen ändern«. Dort finden Sie auch jeweils ein Beispiel.
Garbage Collection Variablen reservieren in JavaScript automatisch einen Platz im Hauptspeicher. Wenn sich dann der Wert im Hauptspeicher ändert, müssten C- und C++-Programmierer den alten Wert von Hand löschen. JavaScript erledigt das automatisch. Dieses Prinzip heißt Garbage Collection.19
19 Für Informatik-Interessierte: Die meisten Browser verwenden Garbage-Collection-Varianten des Mark-and-Sweep-Algorithmus. Er kennzeichnet und entfernt Objekte, auf die von keinem anderen Element verwiesen wird.
KOMPENDIUM
JavaScript
77
Kapitel 3
Syntax und Variablen
3.4
Hilfsmittel
Das nächste Kapitel bietet einen tiefer gehenden Einstieg in die Programmierung. Bevor wir damit beginnen, finden Sie hier noch einige nützliche Hilfsmittel, beispielsweise Kommentare, um Skripten mit eigenen Anmerkungen versehen zu können.
Kommentare Ein Kommentar ist ein Text, der vom JavaScript-Interpreter ignoriert wird. In diesen »ignorierten« Text können Sie also schreiben, was Sie möchten. In der Praxis werden Kommentare verwendet, um den Code zu erklären. Insbesondere bei längeren Skripten ist es sehr wichtig, ausführlich zu kommentieren, denn in einem Jahr wissen Sie sicherlich häufig nicht mehr, wie der alte Code genau aufgebaut war. Außerdem helfen Kommentare beim Austausch von Code zwischen verschiedenen Programmierern. JavaScript unterstützt einzeilige und mehrzeilige Kommentare. Einzeilige Kommentare werden mit zwei Schrägstrichen (//) begonnen. var user = "Meier"; //Variable für den Nutzernamen
Ab der Stelle, wo die Kommentarzeichen eingefügt sind, wird der restliche Text oder Code entwertet. So können Sie natürlich auch ganze Code-Zeilen deaktivieren. Dies ist insbesondere beim Testen und bei der Fehlersuche sinnvoll: // document.write(user);
Mehrzeilige Kommentare werden in /* und */ eingeschlossen. Der gesamte Code dazwischen ist inaktiv. var user = "Meier"; /*Variable für der Nutzername wird deklariert*/ var pass = "test";
Ein mehrzeiliger Kommentar kann auch einen eigens formatierten Block mit einer Beschreibung, beispielsweise einer Funktion20, enthalten: Listing 3.2: Ein Kommentarblock (kommentar.html)
Kommentarblock <script language="JavaScript">
78
KOMPENDIUM
JavaScript
Hilfsmittel
Kapitel 3
function quadrat(x) { return x*x; } /*-----------------------|quadrat() gibt das Qua- | |drat eines Parameters | |zurück. | -------------------------*/ document.write(quadrat(4)); -->
Diese relativ aufwändige Formatierung im Kommentar sorgt zwar für optische Übersichtlichkeit, sollte allerdings erst vorgenommen werden, wenn die Definition der Funktion abgeschlossen und vollständig beschreibbar ist, denn eine nachträgliche Änderung ist je nach Umfang der Dokumentation ein beträchtlicher Mehraufwand.
Konstanten Konstanten sind einmal definierte Werte, die sich im Gegensatz zu Variablen nicht ändern und auch nicht ändern sollen. Konstanten werden in JavaScript mit dem Schlüsselwort const eingeleitet: const Name = Wert;
Leider werden Konstanten zurzeit nur vom Netscape Navigator ab Version 6 und von Mozilla unterstützt. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 3.10: const
Für die Namen (Bezeichner) von Konstanten gelten dieselben Regeln wie für Variablennamen. Im folgenden Beispiel wird der Umrechnungskurs Euro/DM in einer Konstanten hinterlegt und dann dazu verwendet, einen DM-Betrag in Euro umzuwandeln. Konstanten <script language="JavaScript"> Abbildung 3.7: Der Navigator 7 zeigt die korrekte Umrechnung an.
Abbildung 3.8: Der Internet Explorer 6 meldet einen Syntaxfehler, da er const nicht unterstützt.
80
KOMPENDIUM
JavaScript
4
Programmieren
Spricht ein Experte lapidar vom Programmieren, bleibt immer die Frage, worum es dabei eigentlich geht. Eine Webanwendung stellt andere Anforderungen, als eine Windows-Applikation oder ein VBA-Makro. Trotz der unterschiedlichsten Einsatzgebiete sind in vielen Programmiersprachen die Grundstrukturen gleich. In C++, Visual Basic, PHP und auch in JavaScript wird mit Variablen gearbeitet. Diese Variablen müssen mittels Operatoren miteinander verknüpft, Bedingungen müssen überprüft und Anweisungen ausgeführt werden.1 Sollten Sie bereits mit anderen Programmiersprachen vertraut sein, kommt Ihnen also vieles vertraut vor. Es ist ausreichend, wenn Sie einen Blick auf die Syntax werfen. Haben Sie dagegen noch keine Programmiererfahrung, lohnt sich eine ausführlichere Beschäftigung mit den Grundlagen in diesem Kapitel. Sie können später immer wieder darauf zurückgreifen.
4.1
Operatoren
Operatoren verbinden in Variablen gespeicherte Daten. Die verschiedenen mathematischen Rechenarten wie Addition, Subtraktion usw. haben jeweils eigene Operatoren. Für die Addition steht beispielsweise das Pluszeichen (+). Darüber hinaus gibt es noch weitere Operatoren, beispielsweise um zwei Werte miteinander zu vergleichen. Einen Operator haben Sie bereits kennen gelernt: den Zuweisungsoperator (das Ist-Gleich). Er weist einer Variablen einen Wert zu: var x = 5;
Arithmetische Operatoren Die arithmetischen Operatoren sind für die mathematischen Grundrechenarten, beispielsweise Addition und Multiplikation, zuständig. Die Syntax ist sehr einfach. Folgende Zeile addiert 5 und 3 und weist das Ergebnis 8 der Variable x zu. 1
Zugegeben, das ist nur ein kleiner Teil des Programmierens im weiteren Sinne. Für dieses Kapitel wird der Begriff sehr eng gefasst.
KOMPENDIUM
JavaScript
81
Kapitel 4
Programmieren var x = 5 + 3;
Der Operator ist in diesem Fall das Plus-Symbol für die Addition. Die zwei Werte 5 und 3 werden als Operanden2 bezeichnet. In den Beispielskripten dieses Buches sind Operanden und Operatoren jeweils durch ein Leerzeichen getrennt. JavaScript erfordert dies nicht, allerdings werden die Skripten dadurch übersichtlicher. Das folgende Beispiel ist ein komplett lauffähiges Skript. Es rechnet einen in der Variable dm gespeicherten Geldwert von DM in Euro um und gibt ihn aus. Dazu wird die Variable dm durch den Umrechnungskurs (Variable kurs) geteilt. Listing 4.1: Einfache Umrechnung von DM in Euro (euro.html)
Euro in DM <script language="JavaScript">
document.write(euro); //-->
Beachten Sie, dass der arithmetische Operator für die Division kein Doppelpunkt, sondern ein Schrägstrich (/) ist. Natürlich können auch mehrere arithmetische Operatoren hintereinander eingesetzt werden. Dabei gilt – wie in der »echten« Mathematik – die Regel »Punkt vor Strich«. Das heißt, Division und Multiplikation rangieren in der Präferenz vor Addition und Subtraktion. Ein einfaches Beispiel illustriert dies: Listing 4.2: Bei den arithmetischen Operatoren gilt Punkt vor Strich (punkt_vor_strich. html).
Punkt vor Strich <script language="JavaScript">"); 2
82
Frei übersetzt hieße das wohl: »diejenigen, mit denen der Operator arbeitet«.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
var y = (100 + 200) / 2; document.write("y: " + y);
//-->
Das Beispiel besteht aus zwei Teilen: 1.
Im oberen Teil des Skripts wird die Variable x definiert. Sie erhält als Wert das Ergebnis einer Berechnung. Zuerst wird 200 durch 2 geteilt. Das Ergebnis (100) wird mit 100 addiert. Die Variable x erhält also den Wert 200, der anschließend ausgegeben wird.
2.
Der untere Teil des Skripts umgeht das Punkt-vor-Strich-Prinzip mit Klammern. Klammern sind im Prinzip auch Operatoren, die außerdem eine höhere Präferenz als arithmetische Operatoren besitzen. Im Beispiel rechnet der JavaScript-Interpreter zuerst 100 plus 200 und teilt das Ergebnis (300) anschließend durch 2. Ausgegeben wird dann 150 als Wert von y.
Bisher kamen in den Beispielen nur Addition und Division vor. In der folgenden Tabelle finden Sie alle arithmetischen Operatoren im Überblick. Operator
Beispiel
Beschreibung
+
x = 5 + 3; // Ergebnis: 8
Addition; addieren zweier Zahlen
-
x = 5 - 3; // Ergebnis: 2
Subtraktion; eine Zahl wird von der anderen subtrahiert.
-
x = 5; y = -x; //Ergebnis y: -5
Negation mit vorangestelltem Minus-Symbol. Vorzeichenwechsel
*
x = 5 * 3; // Ergebnis: 15
Multiplikation; zwei Zahlen werden miteinander multipliziert.
/
x = 5 / 3; // Ergebnis: 1.6666
Division; eine Zahl wird mit der zweiten Zahl dividiert.
%
x = 5 % 3; // Ergebnis: 2
Modulo Divisionsrest errechnen; im Beispiel: 3 passt in 5 einmal, als Rest bleibt 2.
Tabelle 4.1: Die arithmetischen Operatoren
Inkrement und Dekrement JavaScript hat einen eigenen Operator, das so genannte Inkrement, um einen Wert genau um 1 zu erhöhen. Er wird durch ein doppeltes Pluszeichen (++) symbolisiert und insbesondere bei Schleifen recht häufig zum Erhöhen des Zählers eingesetzt (siehe Kapitel 4.3 »Schleifen«).
KOMPENDIUM
JavaScript
83
Kapitel 4
Programmieren var x = 2; x++;
Diese zwei Zeilen definieren x zuerst mit dem Wert 2 und erhöhen x dann um 1 auf 3. Das Gegenstück zum Inkrement ist das Dekrement zum Verringern eines Wertes um 1. Die Funktionsweise ist analog: var x = 2; x--;
ergibt also den Wert 1 für x. Reihenfolge Bei Inkrement und Dekrement ist entscheidend, ob sie vor oder hinter der Variablen oder dem zu ändernden Wert stehen. ++x;
Stehen Sie wie in dieser Zeile vor der Variablen, wird zuerst der Variablenwert erhöht, bevor die Variable verwendet wird. var x = 5; var a = 3 + ++x;
Bei diesen Zeilen hat also a den Wert 9 ( 3 + 5 + 1). x hat nach den zwei Zeilen den Wert 6. Steht das Inkrement oder Dekrement hingegen hinter der Variablen, wird deren Wert erst um eins erhöht oder gesenkt, wenn die Variable verwendet wurde: var x = 5; var a = 3 + x++; a hat hier also den Wert 8, x wie im vorhergehenden Beispiel den Wert 6.
Kurzformen Inkrement und Dekrement sind zwar sehr praktisch, häufig soll der Wert einer Variablen allerdings nicht nur um 1 verändert werden. In der umständlicheren Variante sieht dies wie folgt aus: var x = 5; x = x - 3; //Ergebnis: 2
84
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Für die zweite Zeile gibt es allerdings auch eine elegantere Kurzform: x -= 3; //Ergebnis: 2
Was geschieht hier? Der Operator wird vor das Pluszeichen geschrieben. Das signalisiert dem Interpreter, dass er den Variablenwert verändern soll. Um welchen Wert er verändert werden soll, steht nach dem Ist-Gleich. Diese Kurzform gibt es für alle arithmetischen Operatoren (siehe Tabelle 4.2). Operator
Beispiel (var x = 5)
Längere Alternative
+=
x += 3; // Erg: 8
x = x + 3;
-=
x -= 3; // Erg: 2
x = x - 3;
*=
x *= 3; // Erg: 15
x = x * 3;
/=
x /= 3; // Erg: 1.6666
x = x / 3;
%=
x %= 3; // Erg: 2
x = x % 3;
Tabelle 4.2: Kurzformen für arithmetische Operatoren
String-Operator Natürlich lassen sich mit Zeichenketten keine Berechnungen anstellen. Dennoch gibt es einen Operator: das Plus-Symbol (+). Es verbindet mehrere Strings miteinander. Listing 4.2 macht davon bereits Gebrauch. Die Verknüpfung von Strings wird auch Konkatenation genannt. var titel = "Yesterday"; var text = "all my trouble ..."; document.write(titel + text);
Die oberen Zeilen fügen den Anfang des Beatles-Klassikers »Yesterday« aneinander und geben ihn aus. Allerdings gibt es dabei ein Problem. Da keine Leerzeichen als Zwischenräume vorgesehen sind, wird der Text direkt aneinander gehängt (siehe Abbildung 4.1). Dieses Problem ist in der Praxis ein sehr häufiger Flüchtigkeitsfehler. Im Prinzip ist es unerheblich, ob Sie das Leerzeichen in den ersten oder zweiten String einfügen. Im Allgemeinen wirkt es allerdings im ersten übersichtlicher.
KOMPENDIUM
JavaScript
85
Kapitel 4
Programmieren
Abbildung 4.1: Der Browser hängt den Text direkt aneinander.
Listing 4.3: Der String-Operator verknüpft zwei Zeichenketten (string_operator. html).
String-Operator <script language="JavaScript">
//--> Abbildung 4.2: Jetzt ist der Abstand korrekt.
Kurzform Für den String-Operator gibt es wie bei der normalen Addition die Kurzform +=. Das Beispiel sieht in der Kurzform mit nur noch einer Variablen wie folgt aus: var text = "Yesterday, "; text += "all my trouble…" document.write(text);
86
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Vergleichsoperatoren Vergleichen ist in der Programmierung gang und gäbe. Es werden keine »Äpfel mit Birnen«, sondern meistens Zahlen miteinander verglichen, um Bedingungen zu überprüfen. Bedingungen kommen insbesondere in Kontrollstrukturen und Schleifen zum Einsatz (siehe Kapitel 4.2 »Kontrollstrukturen« und Kapitel 4.3 »Schleifen«). Die Vergleichsoperatoren sind größtenteils ebenfalls bereits im Mathematikunterricht zum Einsatz gekommen. Folgende Zeile stellt beispielsweise fest, ob 4 größer als 3 ist. var v = (4 > 3);
Das Ergebnis eines Vergleichs ist immer ein Wahrheitswert (Boolean), also true (wahr) oder false (falsch). In unserem Beispiel lautet das Ergebnis natürlich … true. Sie können das feststellen, indem Sie die Variable einfach ausgeben (siehe Abbildung 4.3). Abbildung 4.3: Die Ausgabe von 4 > 3 (vergleich.html)
Eine vollständige Auflistung der Vergleichsoperatoren in JavaScript finden Sie in Tabelle 4.3. Operator
Beispiel
Beschreibung
==
var a = (4 == 3); //Erg: false
Gleichheit
!=
var a = (4 != 3); //Erg: true
Ungleichheit
<
var a = (4 < 3); //Erg: false
Kleiner als
<=
var a = (4 <= 3); //Erg: false
Kleiner als oder gleich
>
var a = (4 > 3); //Erg: true
Größer als
>=
var a = (4 >= 3); //Erg: true
Kleiner als oder gleich
KOMPENDIUM
JavaScript
Tabelle 4.3: Die Vergleichsoperatoren
87
Kapitel 4
Programmieren Sind zwei Zahlen gleich groß, ergibt ein Vergleich mit < oder > immer false. Soll bei Gleichheit true zurückgegeben werden, müssen Sie <= und >= verwenden. Beachten Sie außerdem, dass der Vergleich auch Nachkommastellen berücksichtigt. Der Gleichheitsoperator == wird in der Praxis häufig mit dem Zuweisungsoperator = vertauscht. Das Problem ist, dass JavaScript-Interpreter in diesem Fall manchmal keine Fehlermeldung liefern. Die Schwierigkeit liegt also darin, das Problem zu lokalisieren (zur Fehlerkorrektur siehe Kapitel 9 »Debugging«). Datentypen Ist einer der Operanden keine Zahl, sondern ein anderer Datentyp, führt der JavaScript-Interpreter eine automatische Typkonvertierung durch: Ist einer der Operanden ein String und der andere eine Zahl, wird der String in eine Zahl umgewandelt. Ist einer der Operanden ein Wahrheitswert, wird true in 1 und false in 0 umgewandelt. Ist einer der Operanden ein Objekt, testet der Interpreter, ob das Objekt die Methode toString() (zur Umwandlung in eine Zeichenkette) oder valueOf() (zur Umwandlung in eine Zahl) besitzt. Wenn dies der Fall ist, wird umgewandelt, ansonsten gibt der Browser eine Fehlermeldung aus. Genau gleich (===) und ungleich (!==) Seit JavaScript 1.3 gibt es die Operatoren genau gleich (===)3 und ungleich (!==). Sie überprüfen nicht nur, ob die Werte der zwei Operanden gleich bzw. ungleich sind, sondern auch, ob die Datentypen identisch sind. In den ECMAScript-Standard wurden die beiden Operatoren mit der Version 3 übernommen. Die Browserkompatibilität entnehmen Sie Tabelle 4.4. Ältere Browser unterstützen diese Operatoren nicht.
Tabelle 4.4: Genau gleich und genau ungleich
NS4.x NS6 === !==
3
88
()
NS7
IE4 IE5
IE5.5 IE6
O6
M1
K3
Der Operator genau gleich (===) wird auch Identitätsoperator genannt.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Wenn Sie im Netscape Navigator 4.x als Sprachversion JavaScript 1.2 angeben (language="JavaScript1.2"), werden die Operatoren genau gleich und genau ungleich wie der normale Gleichheits- bzw. Ungleichheitsoperator behandelt. Das vermeiden Sie, indem Sie die bei der Sprachangabe die Versionsnummer weglassen. Ein einfaches Beispiel zeigt dies. Das folgende Skript vergleicht eine Zahl mit einer Zeichenkette: Bei der Verwendung des normalen Gleichheitsoperators == wird die Zeichenkette automatisch in eine Zahl konvertiert. Der Vergleich bei der Variablen x ergibt also true. var a = 4; var b = "4"; var x = (a == b);
Mit dem Operator genau gleich === wird zusätzlich zum Wert auch der Typ verglichen. Da es sich hier um einen String und eine Zahl handelt, ist das Ergebnis false. var y = (a === b);
Hier der vollständige Code: Vergleichsoperatoren <script language="JavaScript">
Der Genau-ungleich-Operator ist das Gegenstück zu genau gleich. Er liefert true, wenn zwei Werte ungleich sind und/oder unterschiedliche Datentypen haben. var a = 4; var b = "4"; var x = (a !== b);
KOMPENDIUM
JavaScript
89
Kapitel 4
Programmieren ergibt also true, obwohl nicht die Werte, sondern nur der Datentyp ungleich sind.
Abbildung 4.4: Der Vergleich mit == liefert true, === ergibt false.
Bei einigen Vergleichen von Spezialwerten unterscheiden sich die genauen und die normalen Vergleichsoperatoren ebenfalls: –
Die Werte null und undefined sind beim Vergleich mit == immer gleich, beim Vergleich mit === dagegen ungleich.
–
Beim Vergleich mit == sind 1 und true bzw. 0 und false gleich, beim Vergleich mit === dagegen nicht.
Vergleich von Strings Der Vergleich zweier Zeichenketten miteinander ist ein Fall, der bisher noch nicht aufgetreten ist. Zuerst die gute Nachricht: Der Vergleich ist möglich. Und nun die schlechte: Da der ASCII-Code des jeweiligen Zeichens die Grundlage bildet, ist der Vergleich häufig nicht praxistauglich. Ein einfaches Beispiel macht den Anfang: var a = "Yesterday"; var b = "Yesterday"; var x = (a == b);
Die Variable x hat nun den Wert true, da die beiden Zeichenketten genau identisch sind. Beim Vergleich überprüft der JavaScript-Interpreter jedes Zeichen von links nach rechts. Wenn auch nur ein Zeichen unterschiedlich ist, ergibt der Vergleich sofort false. Bis jetzt war es noch einfach; bei einem Kleiner-als-Vergleich wird es bereits schwieriger: var a = "a"; var b = "b"; var x = (a < b);
90
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Hier wird der ASCII-Code des kleinen a (95) mit dem des kleinen b (96) verglichen. Da 95 kleiner als 96 ist, ergibt der Vergleich true. Ein weiteres Beispiel, das die Grenzen dieses Vergleichsverfahrens zeigt: var a = "a"; var b = "B"; var x = (a < b);
Das große B befindet sich wie alle Großbuchstaben in der ASCII-Tabelle vor den Kleinbuchstaben. Es hat den ASCII-Code 66. Daraus folgt, dass in diesem Fall der Vergleich false ergibt. Das kleine a ist also größer als das große B. Sind zwei Zeichenketten unterschiedlich lang, vergleicht der Interpreter dennoch von links nach rechts. var a = "abe"; var b = "Yesterday"; var x = (a < b);
ergibt also false. Sind die Zeichenketten allerdings bei allen vorhandenen Zeichen identisch, ist immer die längere Zeichenkette größer. var a = "Yes"; var b = "Yesterday"; var x = (a < b);
ergibt also true. Unter http://www.asciitable.com/ finden Sie eine übersichtliche ASCII-CodeTabelle. Eine Alternative zu den Vergleichsoperatoren bietet die Methode String.localeCompare(). Sie ist neu in JavaScript 1.5 und deswegen nur in
Abbildung 4.5: Eine übersichtliche ASCII-Code-Tabelle
Die Funktion hat folgende Syntax: String1.localeCompare(String2)
Als Ergebnis wird 0 ausgegeben, wenn beide Strings gleich sind, 1, wenn String1 größer ist und -1, wenn String 2 größer ist.4 Für den Vergleich wird der (eingestellte) Zeichensatz des lokalen Betriebssystems verwendet, auf dem der Browser läuft. Folgender Beispiel-Code zeigt die Anwendung von localeCompare() und ergibt die Bildschirmausgabe x: 1.
4
92
Der Opera liefert bei Ungleichheit nicht 1 und -1, sondern einen größeren positiven oder negativen Wert.
Abbildung 4.6: Beachten Sie, dass die Ausgabe von localeCompare()
kein Wahrheitswert ist.
Logische Operatoren Mehrere Vergleiche mit Vergleichsoperatoren müssen in irgendeiner Form miteinander kombiniert werden. Dafür sorgen die logischen Operatoren. Negation (!) Die Negation mit dem Ausrufezeichen kehrt einen Wahrheitswert (Boolean) um. Aus true wird also false und umgekehrt: var x = !true;
ergibt x also den Wert false. In der Praxis wird dies häufig bei Bedingungsüberprüfungen eingesetzt. Ein einfaches Beispiel: Wenn Sie die Funktion isNaN(Wert) einsetzen, erhalten Sie false, wenn es sich bei dem überprüften Variablenwert (Wert) um eine Zahl handelt. Soll Ihre Bedingung allerdings true liefern, wenn es sich um eine Zahl handelt, müssen Sie den Wahrheitswert mit der Negation umdrehen: var a = "test"; var x = !isNaN(a);
KOMPENDIUM
JavaScript
93
Kapitel 4
Programmieren Dieser Code liefert also false. Logisches UND (&&) Das logische UND verknüpft zwei Vergleiche und ergibt nur dann true, wenn beide Vergleiche true liefern. Das zugehörige Symbol wird aus zwei kaufmännischen Und (&, auch Ampersand) gebildet. Im folgenden Beispiel verknüpft das logische UND die beiden Vergleiche, ob eine Variable größer 4 und kleiner 6 ist. Der Variablenwert muss also zwischen 4 und 6 liegen, damit die Variable x den Wert true erhält.
Listing 4.6: Der Einsatz des logischen UND (logisch.html)
Die Bildschirmausgabe ist x: true, da die Variable a = 5 zwischen 4 und 6 liegt. Logisches ODER (||) Das logische ODER liefert im Gegensatz zum logischen UND bereits true, wenn nur einer der beiden Vergleiche den Wert true, der andere aber den Wert false hat. Ein einfaches Beispiel illustriert dies. Die Variable x erhält den Wert true, obwohl nur der zweite Vergleich true ergibt, der erste dagegen false: Listing 4.7: Das logische ODER (logisch_oder.html)
Logisches ODER <script language="JavaScript"> 4);
document.write("x: " + x);
94
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
//-->
Beim Einsatz des logischen ODER kann sich der deutsche Sprachgebrauch als gefährlich erweisen: Das logische ODER liefert auch dann true, wenn beide Vergleiche true liefern. Das »oder« im Deutschen bezeichnet dagegen normalerweise ein »entweder … oder ...«. Short-circuit Mit dem Begriff Short-circuit wird ein besonderes Verhalten des JavaScriptInterpreters beschrieben. Wenn der erste Operand beim logischen UND false ist, ergibt die logische Operation zwangsweise false. In diesem Fall überprüft der Interpreter den zweiten Operanden – und damit den zweiten Vergleich – nicht mehr. Dadurch wird Rechenzeit und -performance gespart. var x = (3 > 4 && 5 > 2);
In diesem Beispiel prüft der Interpreter nicht mehr, ob 5 größer 2 ist, sondern bricht vorher ab. Beim logischen UND steht das Ergebnis true bereits fest, wenn der erste Operand true ergibt. Auch hier wird der zweite Operand nicht geprüft: var x = (3 < 4 || 5 < 2);
Dieses Verhalten ist eigentlich sehr sinnvoll, Sie sollten allerdings bedenken, dass beispielsweise eine Funktion im zweiten Operanden unter Umständen gar nicht mehr aufgerufen wird. Das Short-circuit-Verhalten des Interpreters ist eine leichte Abweichung von der normalen Booleschen Algebra. Das logische UND sowie das logische ODER entsprechen also nicht ganz der grundlegenden Definition der booleschen Algebra. In der Praxis ist dieser Unterschied allerdings vernachlässigbar. Enthält der erste Operand keinen Vergleich und auch keinen Wahrheitswert, wird er standardmäßig als true angesehen. var x = (5 && true);
ergibt also true. Ist der zweite oder sind beide Operanden keine Wahrheitswerte, wird der zweite Operand ausgegeben.
KOMPENDIUM
JavaScript
95
Kapitel 4
Programmieren Dieses Verhalten ist allerdings nicht – obwohl beobachtbar – festgeschrieben. Daher sollten Sie sich in der Programmierung nicht darauf verlassen. Logische Operatoren mischen Natürlich lassen sich logische Operatoren beliebig miteinander kombinieren. Zusätzlich mit den Vergleichsoperatoren ergeben sich damit alle Möglichkeiten, auch für komplexe Überprüfungen. Eine kleine Quizfrage: Welches Ergebnis liefert der folgende Code?
Logische Operatoren mischen <script language="JavaScript">
a b c x
= = = =
5; 2; 3.5; (!(a > b) || ((a > c) && (c > b)));
document.write("x: " + x); //-->
Die lange Zeile mit den logischen Operatoren lässt sich einfach notieren, wenn wir die Ergebnisse der Vergleiche hineinschreiben: (!true) || (true && true)
Jetzt wird es klarer: Der erste Vergleich liefert true. Dies wird mit der Negation umgekehrt. Der eine Operand des logischen ODER-Vergleichs liefert also false. Der andere muss vom Interpreter noch überprüft werden. Er enthält ein logisches UND, dessen Operanden beide den Wert true haben. Daraus folgt, dass das logische UND true zurückgibt; der zweite Operand des logischen ODER ist also true und damit bleibt auch das Ergebnis, der Wert der Variable x, true.
Bitweise Operatoren Die bitweisen Operatoren (auch Bitoperatoren) dienen dazu, Daten auf BitEbene zu vergleichen und zu verschieben. Ein Computer speichert alle Daten in Bits. Ein Bit kann nur zwei Werte, 0 und 1, annehmen5.
5
96
Da es sich um zwei mögliche Werte handelt, spricht man auch von Binärwert. Die zugehörige Schreibweise für Daten ist die Binärschreibweise.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4 Abbildung 4.7: Ein Test im Browser bestätigt das Ergebnis true.
In der Praxis werden die bitweisen Operatoren relativ selten eingesetzt. Sollten Sie also wenig Zeit oder Interesse an diesem Thema haben, können Sie den Abschnitt überspringen. Alle Interessierten finden hier zuerst ein kleines Beispiel, anschließend eine Tabelle mit allen verfügbaren Operatoren und zum Schluss eine Umrechnung aus der dezimalen in die binäre Schreibweise. Die binäre Schreibweise besteht aus einem so genannten Muster. Das Muster hat so viele Stellen, wie die Zahl Bit hat. Eine 4 Bit-Zahl hat also vier Stellen und kann 24 Zahlen darstellen. Die bitweisen Operatoren behandeln intern alle Zahlen wie 32 Bit-Werte. 0010
Das obige Bit-Muster steht für die ganze Zahl 2. Ein Bit-Muster liest sich am besten von rechts nach links. Die rechte Zahl steht für die 1, die zweite von rechts für die 2, die dritte für die 4, die vierte für die 8, die fünfte für … raten Sie! Es geht immer in Zweier-Potenzen, also ist die nächste 24 = 16. Um die binäre Schreibweise in die dezimale umzurechnen, müssen Sie also immer an der Stelle, an der eine 1 steht, die jeweilige Zahl der Stelle addieren: 1010
ergibt also 8 + 0 + 2 + 0 = 10. Die bitweisen Operatoren wandeln Zahlen intern automatisch in dieses binäre Muster um und bearbeiten es. Das bitweise ODER (|) beispielsweise erstellt ein neues Muster und schreibt an alle Stellen eine 1, an denen in beiden Operanden ebenfalls eine 1 vorkommt: 1010 | 0011
ergibt also 1011. Aus den dezimalen Zahlen 10 (1010) und 3 (0011) wird also 11 (1011). Die übrigen bitweisen Operatoren finden Sie in Tabelle 4.6.
KOMPENDIUM
JavaScript
97
Kapitel 4
Programmieren Beachten Sie, dass die direkte Eingabe von Bit-Mustern in JavaScript nicht möglich ist. Bit-Muster mit beginnender 0 werden vom Interpreter als oktale Schreibweise interpretiert (siehe Kapitel 3.1 Abschnitt »Oktale Schreibweise«). Bit-Muster mit beginnender 1 dagegen liest er als normale Zahlen. Sie müssen also normale Zahlen nehmen. Der Interpreter wandelt sie dann intern in die binäre Schreibweise um, führt die Operationen durch und gibt eine normale Zahl zurück. Tabelle 4.6 verwendet bei den Beispielen nur daher die Bit-Muster, um die Funktionsweise der Operatoren zu verdeutlichen.
Tabelle 4.6: Die bitweisen Operatoren
98
Operator
Beispiel
Beschreibung
&
1010 & 0011 //Erg: 0010 = 2
Bitweises UND; schreibt an die Bits eine 1, an denen in beiden Operanden eine 1 vorkommt.
|
1010 | 0011 //Erg: 1011 = 11
Bitweises ODER; schreibt an die Stellen eine 1, an denen in einem oder beiden der Operanden 1 vorkommt.
^
1010 ^ 0011 //Erg: 1001 = 9
Bitweises ENTWEDER ODER; stellt an die Bits eine 1, an denen nur in einem der beiden Operanden 1 vorkommt.
~
~1010 //Erg: 0101 = 5
Bitweise Negation; ändert alle Bits des Operanden. Aus 0 wird 1 und umgekehrt. Das Tastenkürzel für das Symbol ist (AltGr) + (+).
<<
1010 << 2 //Erg: 101000 = 40
Bitweise Verschiebung nach links. Verschiebt das Binärmuster des linken Operanden um die im rechten Operanden angegebenen Stellen nach links. Die rechte Seite wird durch Nullen aufgefüllt. Der rechte Operand sollte maximal 31 betragen, da in JavaScript mit 32 Bit und damit 32 Stellen gearbeitet wird. Die Verschiebung um eine Stelle entspricht einer Multiplikation der Zahl mit 2. Zwei Stellen sind dementsprechend eine Multiplikation mit 4, drei Stellen eine mit 8 usw.
KOMPENDIUM
JavaScript
Operatoren
Kapitel 4
Operator
Beispiel
Beschreibung
>>
1010 >> 2 //Erg: 0010 = 2
Bitweise Verschiebung nach rechts um die vom rechten Operanden angegebenen Positionen (maximal 31). Die Bits, die rechts überstehen, werden gelöscht. Hat der linke Operand ein negatives Vorzeichen, wird links mit Einsen aufgefüllt, ansonsten mit Nullen. Das Verschieben um ein Bit nach rechts entspricht der Division durch 2 (ohne Rest), das um zwei der Division durch 4 usw.
>>>
1010 >>> 2 //Erg: 0010 = 2
Bitweise Verschiebung nach rechts. Dabei gehen die Bits, die rechts herausfallen, verloren. Die Bits links werden mit Nullen aufgefüllt.
Tabelle 4.6: Die bitweisen Operatoren (Forts.)
Für alle bitweisen Operatoren gibt es wie bei arithmetischen Operatoren die Kurzform mit integrierter Zuweisung: x <<= 2;
steht also für x = x << 2;
Das folgende Beispiel verwendet die selbst geschriebene Funktion binaer(), um einen Dezimalwert von 0 bis maximal 255 in einen Binärwert umzuwandeln. Dabei kommen folgende Elemente zum Einsatz: Ein Formularfeld enthält den Dezimalwert. Wenn der Nutzer etwas eingibt, wird der Event-Handler6 onchange aktiviert. Er ruft die Funktion binaer() auf. dezimal (bis 255)
Einige Elemente in diesem Beispiel waren noch kein Bestandteil der vorangegangenen Kapitel, sondern werden später behandelt. Beispielsweise wird der Umgang mit Formularen detaillierter in Kapitel 16 »Formulare« behandelt. In der Funktion wird zuerst auf die vom Nutzer in das Formularfeld mit dem Dezimalwert eingegebene Zahl zugegriffen. Sie wird der Variablen zahl als Wert zugewiesen. 6
Ein Event-Handler reagiert auf ein Ereignis. Mehr zu Ereignissen erfahren Sie in Kapitel 11 »Ereignisse und Event-Handler«.
KOMPENDIUM
JavaScript
99
Kapitel 4
Programmieren var zahl = formular.dec.value;
Anschließend definieren wir 8 Variablen für die 8 Bit der binären Zahl. Sollten Sie mehr als 255 Dezimalwerte umrechnen möchten, müssen Sie entsprechend mehr Bits verwenden. var bit8 = 0, bit7 = 0, bit6 = 0, bit5 = 0; var bit4 = 0, bit3 = 0, bit2 = 0, bit1 = 0;
Nun wird für jedes Bit überprüft, ob an dieser Stelle eine 1 im Bit-Muster vorhanden ist. Dazu dient ein Binärvergleich mit & für jede einzelne Stelle. Erläutern wir dies beispielhaft für 128: 128 wird in der Binärschreibweise 10000000 geschrieben. Vergleichen wir es mit der vom Nutzer eingegebenen Zahl, wird beim logischen UND entweder 10000000 zurückgegeben, wenn die eingegebenen Zahl im achten Bit eine 1 besitzt, oder der Vergleich liefert 00000000. Das letzte Ergebnis entspricht 0 (false) und erfüllt damit die Bedingung der if-Anweisung7 nicht. Die Variable bit8 wird dann nicht auf 1 gesetzt, sondern bleibt 0. if (zahl & 128) { bit8 = 1; }
Sobald der Vergleich für alle Bits durchgeführt ist, schreibt das Skript das Ergebnis in das Formularfeld für den Binärwert. formular.bin.value = ("" + bit8 + bit7 + bit6 + bit5 + bit4 + bit3 + bit2 + bit1);
Im Folgenden finden Sie den vollständigen Code: Listing 4.9: Die Umrechnung von dezimaler in binäre Schreibweise (bitweise.html)
In Abbildung 4.8 sehen Sie das Ergebnis: eine automatische Umwandlung von dezimalen in binäre Werte. Abbildung 4.8: Der Dezimalwert wird »live« in die binäre Schreibweise umgewandelt.
KOMPENDIUM
JavaScript
101
Kapitel 4
Programmieren
Operator-Präferenz Bei den arithmetischen Operatoren ist es bereits angeklungen: Operatoren werden vom JavaScript-Interpreter immer in einer festgesetzten Reihenfolge, der Operator-Präferenz, abgearbeitet. Für die arithmetischen Operatoren entspricht die Reihenfolge der bekannten Punkt-vor-Strich-Regel, Multiplikation und Division haben also eine höhere Präferenz als Addition und Subtraktion. Die Präferenz gibt es allerdings nicht nur für die arithmetischen Operatoren, sondern für alle Operatoren. In Tabelle 4.1 finden Sie die Operatoren in der Präferenz-Reihenfolge von hoch (15) bis niedrig (1) aufgeführt. Einige der Operatoren sind Ihnen noch nicht bekannt. Wir stellen sie in den folgenden Kapiteln vor.
Tabelle 4.7: Präferenz-Reihenfolge der Operatoren (beginnend bei der höchsten Präferenz 15)
102
Präferenz
Operator
15
. [] () new
14
++ -- (Vorzeichen) ~ ! delete typeof void
13
* / %
12
+ + (Konkatenation)
11
<< >> >>>
10
< <= > >= instanceof
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
Präferenz
Operator
9
== != === !==
8
&
7
^
6
|
5
&&
4
||
3
?:
2
= Kurzformen mit Zuweisung
1
,
4.2
Tabelle 4.7: Präferenz-Reihenfolge der Operatoren (beginnend bei der höchsten Präferenz 15) (Forts.)
Kontrollstrukturen
In der Programmierung ist es essenziell, verschiedene Wahlmöglichkeiten zu haben. Wie soll das Programm wann handeln? Dies steuern die Kontrollstrukturen, allen voran die if-Anweisung, die – weil grundlegend – bereits in einigen Beispielen vorkam.
if-Anweisung Die if-Anweisung leitet sich direkt aus dem Sprachgebrauch ab. Ein Blick auf die Syntax verdeutlicht dies: if (Bedingung) { Anweisung; }
Sie lässt sich einfach vorlesen: »Wenn Bedingung eintritt, führe Anweisung aus«. Die runden Klammern um die Bedingung und die geschweiften Klammern um die Anweisung signalisieren dem Interpreter, wann welcher Teil beginnt.
KOMPENDIUM
JavaScript
103
Kapitel 4
Programmieren Im Sprachgebrauch hat es sich eingebürgert, von der if-Anweisung zu sprechen, wenn das komplette Konstrukt mit Bedingung und darin enthaltener Anweisung gemeint ist. Ist dagegen nur von der Anweisung die Rede, bezieht sich das auf die Anweisung, die ausgeführt wird, wenn die Bedingung erfüllt ist. Die Bedingung enthält meist einen Vergleich mit Vergleichsoperatoren, eventuell auch in Verbindung mit logischen Operatoren. Die Anweisung wird nur ausgeführt, wenn die Bedingung true ist. Ansonsten ignoriert der Interpreter die Anweisung und springt an die Stelle hinter der schließenden geschweiften Klammer. Soll die if-Anweisung ausgeführt werden, wenn die Bedingung false ergibt, drehen Sie das Ergebnis der Überprüfung einfach mit der logischen Negation (!) um. Wie ist das Ergebnis des folgenden Beispiels? Was wird ausgegeben? var groesse = 180; if (groesse > 175) { document.write("Zu groß!"); }
Richtig, der Text »Zu groß!« wird ausgegeben, da die Bedingung der ifAnweisung erfüllt ist. Abbildung 4.9: Der Nutzer ist bereits zu groß für die Sandkiste!
Das vorhergehende Beispiel lässt sich durchaus weiter ausbauen. Was geschieht beispielsweise, wenn die Variable groesse einen geringeren Wert als 175 hat? Um diesen Fall hinzuzufügen, könnten Sie einfach eine weitere if-Anweisung verwenden: if (groesse > 175) { document.write("Zu groß!"); } if (groesse <= 175) { document.write("Du passt noch ins Auto."); }
104
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
else Das letzte Beispiel funktioniert bereits sehr gut. Alle Fälle werden abgedeckt, allerdings sind auch für menschliche Körpergrößen außergewöhnliche Maße mit berücksichtigt. Um das auszuschließen, verfeinern wir die if-Bedingungen ein wenig: if (groesse > 175 && groesse < 240) { document.write("Zu groß!"); } if (groesse <= 175 && groesse > 45) { document.write("Du passt noch ins Auto."); }
Jetzt gibt es allerdings Fälle, die nicht mehr in die Überprüfungen passen, beispielsweise eine Größe unter 45 oder über 240. Die deckt die else-Anweisung ab. else { document.write("Unrealistisch!"); }
Die else-Anweisung wird immer dann ausgeführt, wenn die vorherigen ifAnweisungen nicht zutreffen. Sie ist gewissermaßen das Auffangbecken für alle Fälle, die vorher nicht berücksichtigt werden. Die Syntax sieht wie folgt aus: if (Bedingung) { Anweisung; } else { Anweisung; }
else if Mehrere if-Anweisungen hintereinander werden immer komplett durchgeprüft. Trifft die Bedingung jeweils zu, wird die Anweisung ausgeführt. Dieses Verhalten ist häufig erwünscht, manchmal aber auch unpraktisch. Ein Beispiel: Sie betreiben eine Website mit Mitgliedern, die unterschiedliche Berechtigungsstufen von 1 bis 6 haben. Die 6 Berechtigungsstufen sollen in drei Nutzerklassen eingeteilt werden: Luxusnutzer (5 und 6), Mittelklasse (3 und 4) sowie Einsteigerpakete (1 und 2), die in der Praxis beispielsweise auf drei verschiedene Seiten verlinken könnten. Betrachten Sie die folgende Fallunterscheidung. Erreicht sie das gewünschte Ziel und trennt die drei Klassen?
KOMPENDIUM
JavaScript
105
Kapitel 4
Programmieren var z = 5; if (z >= 5) { document.write("Luxusnutzer"); } if (z >= 3) { document.write("Mittelklasse"); } if (z >= 1) { document.write("Einsteigerpaket"); }
Ein Blick in den Browser zeigt das Problem (siehe Abbildung 4.10). Wenn die Variable z gleich 5 oder 6 ist, treffen alle drei if-Bedingungen zu und der Nutzer wird in jede Klasse eingeordnet. Abbildung 4.10: Der Nutzer ist alle drei Stufen auf einmal.
Um dieses Problem zu umgehen, verwenden Sie das else if-Konstrukt. Es hat folgende Syntax: if (Bedingung) { Anweisung; } else if (Bedingung) { Anweisung; }
Die else if-Bedingung wird nur geprüft, wenn die if-Bedingung nicht zutrifft. Im Beispiel ist es ausreichend, die zwei letzten if-Anweisungen durch else if zu ersetzen: Listing 4.10: Die else if-Anweisung (else_if.html)
document.write("Luxusnutzer"); } else if (z >= 3) { document.write("Mittelklasse"); } else if (z >= 1) { document.write("Einsteigerpaket"); }
//--> Abbildung 4.11: Nun funktioniert die Unterscheidung.
Das hier beschriebene Problem ist natürlich auch auf anderem Wege lösbar. Beispielsweise ließen sich die Bedingungen der if-Anweisungen so anpassen, dass es nicht mehr zu Überschneidungen kommt: if (z == 3 || z == 4) { else if ist allerdings ein schneller und einfacher Weg.
Ursprünge von else if In vielen JavaScript-Büchern und Referenzen taucht else if nicht auf. Dies ist – zumindest unter Gesichtspunkten der vollständigen Sprachabdeckung – kein Versäumnis, da else if ein Konstrukt ist, das aus if- und else-Anweisungen gebildet wird. Die else if-Anweisung besteht aus einer else-Anweisung, bei der einfach die geschweiften Klammern weggelassen wurden (siehe nächster Abschnitt »Kurzformen«). Die else-Anweisung erhält als Anweisung ein if. Verständlich wird dies, wenn man sich die Langform zur else-if-Syntax anschaut: if (Bedingung) { Anweisung; } else { if (Bedingung) { Anweisung; } }
KOMPENDIUM
JavaScript
107
Kapitel 4
Programmieren Mehrere else if-Anweisungen hintereinander sind also lediglich ineinander verschachtelte else- und if-Anweisungen. Unser Beispiel sieht in der Langform wie folgt aus:
Listing 4.11: Die lange Version von else-if (else_if_lang.html)
else if-Anweisung <script language="JavaScript">= 5) { document.write("Luxusnutzer"); } else { if (z >= 3) { document.write("Mittelklasse"); } else { if (z >= 1) { document.write("Einsteigerpaket"); } } }
//-->
Achten Sie insbesondere auf die Einrückungen. Funktional gibt es keine Unterschiede, die else if-Konstruktion ist allerdings wesentlich übersichtlicher als die Langform. Kurzformen Die else if-Konstruktion zeigt bereits eine Kurzform der if-Anweisung. Sie können die geschweiften Klammern weglassen. Normalerweise allerdings nur, wenn die Anweisung nur aus einer Zeile besteht. Hat sie mehrere Zeilen, nennt man das auch Anweisungsblock. Ein solcher Block muss in geschweiften Klammern stehen. if (a < 3) document.write(a);
ist also erlaubt. if (a < 3) document.write(a); document.write(++a);
dagegen verboten.
108
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
Hier gibt der JavaScript-Interpreter ++a auf jeden Fall aus, auch wenn a größer 3 ist, da die zweite Anweisung nicht mehr zur if-Anweisung gehört. Für übersichtlichen Code sollten Sie immer geschweifte Klammern verwenden. Eine Ausnahme ist natürlich die else if-Konstruktion. Eine komplette if-Anweisung kann außerdem in nur einer Zeile stehen. if (a <3) document.write(a);
Hier meckert der Browser noch nicht einmal, wenn der Strichpunkt fehlt. Allerdings dürfen Strichpunkt und geschweifte Klammern auch in einer Zeile vorhanden sein: if (a <3) { document.write(a); }
Anweisungen verschachteln Bei der Langvariante von else-if haben Sie bereits gesehen, dass if- und elseAnweisungen beliebig ineinander verschachtelt werden dürfen (siehe Listing 4.11). Das Problem: Irgendwann verliert man als Programmierer die Übersicht. Im Allgemeinen sollten Sie bei einfacheren Anwendungen nicht mehr als drei verschachtelte if-Anweisungen verwenden. Konditionaler Operator (?) Der konditionale Operator ist, wie der Name bereits sagt, eigentlich ein Operator. Er ist sogar noch mehr: der einzige Operator in JavaScript, der drei Operanden haben kann. Bedingung ? Wert 1 : Wert 2
Zuerst wird die Bedingung überprüft. Ist sie erfüllt, liefert der Interpreter den ersten Wert. Ist sie nicht erfüllt, wird der zweite Wert zurückgegeben. In der Praxis bildet der konditionale Operator oft eine Kurzschreibweise für eine einfache if-else-Fallunterscheidung. Statt eines Wertes wird dann eine Anweisung eingetragen, die natürlich auch einen Wert zurückliefert. Im folgenden Beispiel wird überprüft, ob a kleiner 3 ist: (a < 3) ? document.write("a kleiner 3") : document.write("a größer 3");
KOMPENDIUM
JavaScript
109
Kapitel 4
Programmieren Dies entspräche der folgenden if-else-Anweisung: if (a < 3) { document.write("a kleiner 3"); } else { document.write("a größer 3"); }
switch case Die Fallunterscheidung mit switch verwendet einen Ausdruck und prüft mit verschiedenen Fällen, welchen Wert dieser Ausdruck annimmt. switch (Ausdruck) { case Wert1: Anweisung1; break; case Wert2: Anweisung2; break; . . . }
Der Ausdruck wird hinter das Schlüsselwort switch in runde Klammern geschrieben. Meist handelt es sich dabei um eine Variable. Anschließend folgen die einzelnen Fälle. Jeder Fall beginnt mit dem Schlüsselwort case. Dann folgt der Wert, den der Ausdruck annehmen muss, damit der Fall eintritt. Stimmt der Wert mit dem Wert des Ausdrucks überein, wird die Anweisung ausgeführt. break verlässt die switch-Fallunterscheidung, da nach dem Eintreten eines Falls nicht weiter geprüft werden muss. Tritt ein Fall nicht ein, wandert der JavaScript-Interpreter weiter zum nächsten Fall und überprüft dessen Wert. In sehr alten Browsern, Netscape Navigator 2 und Internet Explorer 3 (in beiden Varianten), ist die switch-Anweisung noch nicht enthalten. In aktuellen Browsern ist sie allerdings implementiert. Tabelle 4.8: switch-Anweisung
110
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
Die switch-Anweisung gibt es auch in anderen Programmiersprachen wie Java und C++. Allerdings unterscheidet sich dort häufig die genaue Behandlung. In Visual Basic heißt die entsprechende Anweisung select case. Das folgende Beispiel kommt in der Praxis häufiger vor: In JavaScript werden per Funktion gewonnene Wochentage von 0 (Montag) bis 6 (Sonntag) zurückgeliefert. Möchten Sie daraus deutsche Begriffe machen, bietet sich die switch-Anweisung an. Im folgenden Beispiel verwenden wir nicht das Datumsobjekt von JavaScript, sondern definieren der Einfachheit halber den Wochentag in einer Variablen. Wie Sie mit dem Datumsobjekt arbeiten, erfahren Sie in Kapitel 5 »Funktionen«. Das Beispiel besteht aus mehreren Teilen: Zuerst wird der Wochentag in der Variablen tag gespeichert. Diese Variable ist der Ausdruck, der in der switch-Anweisung ausgewertet wird. Jeder Tag von 0 bis 6 ist ein einzelner Fall. Ihm wird entsprechend die richtige Ausgabe des deutschen Wochentags zugeordnet. Hier das vollständige Skript: switch <script language="JavaScript">
Wenn Sie das Skript testen, wird der richtige Wochentag angezeigt (siehe Abbildung 4.12). Abbildung 4.12: Der richtige Wochentag wird ausgegeben.
Wenn Sie break aus Versehen weglassen, werden alle Anweisungen ab dem zutreffenden Fall ausgeführt. In Abbildung 4.13 ist tag gleich 3, also »Donnerstag«. Da break fehlt, werden allerdings auch »Freitag« bis »Sonntag« ausgegeben. Abbildung 4.13: Ohne break werden alle Anweisungen ab der erfüllten Bedingung ausgeführt.
Typkonvertierung Im Gegensatz zum Einsatz von Vergleichsoperatoren wird in der switchcase-Anweisung keine automatische Typkonvertierung durchgeführt. Folgender Code ergibt also keine Ausgabe, da der Wert der Variablen ein String ist, der zugehörige Fall aber eine Zahl:
112
KOMPENDIUM
JavaScript
Kontrollstrukturen
Kapitel 4
var tag = "3"; switch (tag) { case 0: document.write("Montag"); break; case 1: document.write("Dienstag"); break; case 2: document.write("Mittwoch"); break; case 3:
document.write("Donnerstag"); break; case 4: document.write("Freitag"); break; case 5: document.write("Samstag"); break; case 6: document.write("Sonntag"); break; }
default Wenn wie bei der Verwendung eines falschen Datentyps aus dem vorigen Abschnitt keiner der Fälle eintrifft, ist es oft ärgerlich, dass der Nutzer keine Rückmeldung erhält. Um dieses Problem zu beheben, fügen Sie einfach am Ende eine default-Anweisung an. Sie tritt ein, wenn vorher keiner der Fälle denselben Wert wie der Ausdruck hat. Die Syntax der switch-Anweisung wird um die default-Anweisung erweitert und damit ein wenig länger: switch (Ausdruck) { case Wert1: Anweisung1; break; case Wert2: Anweisung2; break; . default: Anweisung; }
KOMPENDIUM
JavaScript
113
Kapitel 4
Programmieren Wird das Beispiel mit den Wochentagen um eine default-Anweisung erweitert, kann damit auch eine Falscheingabe, beispielsweise der Wert 7 für den Wochentag, abgefangen werden: var tag = 7; switch (tag) { case 0: document.write("Montag"); break; case 1: document.write("Dienstag"); break; case 2: document.write("Mittwoch"); break;
Listing 4.13: Der Einsatz von default
(switch_default. html nicht vollständig abgedruckt)
. . . default: document.write("Keiner der Fälle ist eingetreten");
} Abbildung 4.14: Keiner der sieben Wochentage konnte identifiziert werden.
switch und if im Vergleich Wenn nur mögliche Werte eines Ausdrucks nacheinander ausgewertet werden sollen, wird eine if-Anweisung unnötig kompliziert. Dies zeigt der direkte Vergleich zwischen switch und if: Listing 4.14: Das switchBeispiel, mit if-realisiert (if_switch.html).
if oder switch <script language="JavaScript">
114
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
} else if (tag == 2) { document.write("Mittwoch"); } else if (tag == 3) { document.write("Donnerstag"); } else if (tag == 4) { document.write("Freitag"); } else if (tag == 5) { document.write("Samstag"); } else if (tag == 6) { document.write("Sonntag"); } else { document.write("Kein gültiger Wochentag!"); }
//-->
Zwar ist die if-else if-Variante um einige Zeilen8 kürzer, dafür besteht sie aus einigen Zeichen weniger und fordert damit auch mehr fehlerträchtige Tipparbeit. Außerdem wirkt die switch-Variante optisch aufgeräumter. Schließlich muss jeder selbst abwägen, was ihm besser gefällt. Viele Programmierer greifen automatisch zu if-else if, da sie dieses Konstrukt besser kennen. Behalten Sie aber die Alternative switch im Hinterkopf, wenn es an neue Aufgaben geht.
4.3
Schleifen
Schleifen enthalten stetig sich wiederholende Anweisungen. Sie werden so lange ausgeführt, bis eine vorher festgelegte Bedingung nicht mehr erfüllt ist. Fehlt diese Bedingung oder ist sie immer erfüllt, läuft die Schleife ewig. Man spricht dann von einer Endlosschleife. Endlosschleifen gehören zu den Fehlern, die es unbedingt zu vermeiden gilt, denn häufig stürzt dem Nutzer sonst der Browser ab. Haben Sie beim Programmieren eine Endlosschleife erzeugt, klicken Sie im Browser auf das Stop-Symbol oder betätigen Sie (Esc), um den JavaScriptInterpreter anzuhalten. Manche Browser fragen im Falle einer Endlosschleife auch nach, ob sie das Skript abbrechen sollen (siehe Abbildung 4.15).
8
Um genau zu sein: sieben Zeilen. Natürlich könnten Sie weitere Zeilen einsparen, indem Sie else if-Anweisungen auf eine Zeile komprimieren. Ähnlich lassen sich auch switch-Fälle auf eine Zeile schreiben. Der Nachteil bei beiden Methoden ist, dass die Übersichtlichkeit sehr stark leidet.
KOMPENDIUM
JavaScript
115
Kapitel 4
Programmieren
Abbildung 4.15: Der Internet Explorer 6 erkundigt sich, ob das Skript weiter ausgeführt werden soll.
for Die for-Schleife ist die komfortabelste und daher auch meist verbreitete Schleifenart. Wie oft die Schleife durchlaufen wird, steuern drei Parameter: for (Initialisierung; Bedingung; Änderung) { Anweisungen; }
Die drei Parameter dienen alle zur Steuerung des Schleifenzählers: Bei der Initialisierung wird der Zählervariablen ein erster Wert vergeben. Diese Anweisung wird nur einmal, zu Beginn, ausgeführt. Der Variablenname für die Zählervariable ist natürlich beliebig wählbar. Als Standard eingebürgert hat sich allerdings i. Die Bedingung wird vor jedem Schleifendurchlauf überprüft. Ist sie erfüllt (true), werden die Anweisungen in der Schleife ausgeführt. Nach jedem Schleifendurchlauf wird in der Änderung die Zählervariable angepasst. Dies geschieht so lange, bis die Zählervariable die Bedingung nicht mehr erfüllt und die Schleife abgebrochen wird. Natürlich kann die Zählervariable auch in der Schleife geändert werden und in der Änderung folgen andere Anpassungen. Jeder der drei Schleifenparameter kann weggelassen werden, nicht aber die abtrennenden Strichpunkte. Fehlt die Bedingung, ist sie automatisch immer true. In diesem Fall wird aus der for-Schleife eine Endlosschleife, wenn sie nicht in den Anweisungen mit break abgebrochen wird. Ein einfaches Beispiel gibt die Quadrate der Zahlen von 1 bis 10 aus: Dazu wird der Zähler auf 1 initialisiert. for (var i=1;
116
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
Die Zählervariable muss nicht unbedingt erst in der for-Schleife deklariert werden. Meist wird allerdings diese Technik verwendet, da die Zählervariable nur in der Schleife eingesetzt wird. Hier ist allerdings Vorsicht geboten: selbst wenn die Zählervariable erst in der for-Schleife deklariert wird, steht sie auch nach der Schleife noch zur Verfügung. Sie ist also keine lokale Variable, wie es sie bei Funktionen gibt (siehe Kapitel 5 »Funktionen«). In der Bedingung überprüft die for-Schleife, ob der Zähler kleiner oder gleich 10 ist. for (var i=1; i <= 10;
Die Änderung erhöht den Zähler mit einem Inkrement bei jedem Schleifendurchlauf um 1. for (var i=1; i <= 10; i++) {
Schließlich muss nur noch das Quadrat der Zählervariable im Schleifenkörper ausgegeben werden und fertig ist das Beispiel: for-Schleife <script language="JavaScript">
Komma-Operator (,) Der Komma-Operator ist der Operator mit der niedrigsten Präferenz (siehe Kapitel 4.1 im Abschnitt »Operator-Präferenz«). Er dient dazu, gleichwertige Anweisungen voneinander zu trennen. In einer for-Schleife lassen sich für jeden der drei Parameter mehrere, durch Kommata getrennte, Anweisungen vergeben. Im folgenden Beispiel nutzen wir dies, um eine zweite Zählervariable t einzusetzen, die gegenläufig zur ersten von 10 nach unten gezählt wird. Die beiden Variablen werden in der Anweisung als Produkt i * t ausgegeben:
KOMPENDIUM
JavaScript
117
Kapitel 4
Programmieren
Abbildung 4.16: Die for-Schleife gibt die Quadrate der Zahlen von 1 bis 10 aus.
Listing 4.16: Eine for-Schleife mit mehreren Anweisungen für jeden Parameter (for_komma.html)
Mit dieser Schleife erzeugen Sie eine symmetrische Zahlenfolge (1*10, 2*9, 3*8 … siehe Abbildung 4.17). Abbildung 4.17: Die Schleife ergibt eine symmetrische Zahlenfolge.
118
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
break Die break-Anweisung kennen Sie schon von der switch-Fallunterscheidung (siehe Kapitel 4.2 im Abschnitt »switch case«). Sie lässt sich auch dazu verwenden, for-Schleifen abzubrechen. Der folgende Code würde die Zahlen von 1 bis 100 untereinander ausgeben. Im Schleifenkörper ist allerdings eine if-Überprüfung eingebaut. Sie wird aktiv, wenn die Zählervariable gleich 12 ist und bricht dann die komplette Schleife mit break ab: for und break <script language="JavaScript">");
Listing 4.17: Eine for-Schleife mit break abbrechen (for_break.html)
if (i == 12) { break; }
} //--> Abbildung 4.18: Bei 12 ist dank break Schluss, obwohl der Schleifenzähler bis 100 reicht.
KOMPENDIUM
JavaScript
119
Kapitel 4
Programmieren break können Sie auch bei den anderen Schleifentypen wie while- und do
while-Schleifen einsetzen. continue Der Befehl continue ist das Gegenstück zu break. Er springt zum nächsten Schleifendurchlauf. Allerdings werden alle Anweisungen ignoriert, die nach continue folgen. Das folgende Beispiel nutzt continue, um bei den Zahlen von 1 bis 10 den Bereich von 4 bis 6 wegzulassen. Mit einer if-Anweisung wird überprüft, ob die Zählervariable in diesem Durchlauf zwischen 4 und 6 liegt. Ist dies der Fall, wird der Schleifendurchgang mit continue abgebrochen und gleich der nächste Durchgang gestartet. Dadurch wird die Ausgabeanweisung für die Zählervariable übersprungen. Listing 4.18: continue in einer
for-Schleife (for_continue.html)
for und continue <script language="JavaScript"> 3 && i < 7) { continue; }
document.write(i + " "); } //--> Abbildung 4.19: Die Zahlen 4 bis 6 werden ausgespart.
120
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
continue funktioniert bei allen Schleifentypen, auch while- und do whileSchleifen.
Verschachtelte Schleifen Natürlich können Sie Schleifen beliebig ineinander verschachteln. Folgende Schleifenkombination gibt beispielsweise fünfmal hintereinander die Quadrate der Zahlen von 1 bis 10 aus: for (var i=1; i <= 5; i++) { for (var j=1; j <= 10; j++) { document.write(j*j + " "); } }
Listing 4.19: Ausschnitt von verschachtelten for-Schleifen (for_verschachtelt. html) Abbildung 4.20: Fünfmal hintereinander die Quadrate der Zahlen von 1 bis 10
Achten Sie bei einer verschachtelten Schleife darauf, dass die Zählervariable der inneren Schleife nicht dieselbe sein sollte, wie die der äußeren Variable.
KOMPENDIUM
JavaScript
121
Kapitel 4
Programmieren break und continue in verschachtelten Schleifen
Wenn Sie break oder continue in ineinander verschachtelte Schleifen einsetzen, bezieht sich der Befehl immer auf die Schleife, in der er steht. Häufig ist es aber gewünscht, die äußere Schleife aus einer inneren Schleife zu beenden. Für diesen Fall können Sie Schleifen einen Namen geben und den Namen hinter die break- oder continue-Anweisung schreiben. So erkennt der Interpreter, welche Schleife er beenden muss: Name1: for (Initialisierung; Bedingung; Änderung) { Anweisungen; Name2: for (Initialisierung; Bedingung; Änderung) { Anweisungen; break Name1; } }
Die Möglichkeit, Schleifen zu beschriften, gibt es in den älteren Browsern Netscape 2 und 3 und Internet Explorer 3 in den verschiedenen Varianten nicht. Die aktuellen Browser dagegen unterstützen Schleifen mit Namen. Tabelle 4.9: Schleifen beschriften
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
In der Praxis sind beschriftete Schleifen allerdings relativ selten zu finden, da es nicht so viele Einsatzgebiete für verschachtelte Schleifen gibt bzw. verschachtelte Schleifen häufig für unübersichtlichen Code sorgen. Ein kleines Beispiel illustriert die Funktionsweise der Schleifennamen. Wir beschriften die äußere Schleife mit »schleife1« und die innere mit »schleife2«. In der if-Anweisung in »schleife2« beenden wir die äußere Schleife mit break schleife1, sobald die Zählervariable i der äußeren Schleife den Wert 2 hat. Da dies nach einem Durchlauf der Fall ist, wird nach der Ausgabe der ersten 100 Zahlen gestoppt: Listing 4.20: Verschachtelte und beschriftete Schleifen (verschachtelt_ beschriften.html)
Verschachtelte und beschriftete for-Schleifen <script language="JavaScript">
for (var i=1; i <= 5; i++) {
122
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4 schleife2:
for (var j=1; j <= 100; j++) { if (i == 2) { break schleife1;
} document.write(j + " "); } } //--> Abbildung 4.21: Die Schleife wird nur einmal ausgeführt.
In JavaScript lassen sich nicht nur Schleifen, sondern auch beliebige andere Anweisungen beschriften. Bei Schleifen ist der Einsatz von Namen allerdings am üblichsten und in der Praxis sinnvoll. for-in Die for-in-Schleife ist eine Unterart der for-Schleife mit einem ganz bestimmten Zweck. Sie soll Elemente aus Objekten und Arrays auslesen. Da sowohl Objekte als auch Arrays in den Kapiteln 6 und 7 ausführlich behandelt werden, finden Sie hier nur die Syntax und ein kurzes Beispiel zur for-in-Schleife.
KOMPENDIUM
JavaScript
123
Kapitel 4
Programmieren Die Besonderheit der for-in-Schleife ist der in-Operator9. Ein Blick auf die Syntax verdeutlicht die Funktionsweise: for (Variable in Objekt) { Anweisung }
Die Variable nimmt bei jedem Schleifendurchlauf eine Eigenschaft des Objekts auf. Beendet wird die Schleife, wenn alle Eigenschaften eines Objekts durchlaufen sind. Anhand eines Arrays wird das verständlicher. Ein Array besteht aus beliebig vielen Daten, die standardmäßig mit einem ganzzahligen Index versehen werden, der bei 0 beginnt: Im folgenden Array hat »München« den Index 0, »Frankfurt« den Index 1 und »Berlin« den Index 2. var a = new Array("München", "Frankfurt", "Berlin");
Eine for-in-Schleife liest das Array aus: for (var index in a) {
In der Variablen index wird die Indexnummer der verschiedenen ArrayElemente gespeichert. Im ersten Schleifendurchlauf ist das 0, im zweiten 1, im dritten 2. Ein vierter Durchlauf erfolgt nicht, da das Array nur drei Elemente hat. Die Schleife wird beendet. Im Schleifenkörper können Sie jetzt mit dem Index arbeiten. Die folgende Zeile gibt zuerst den Index aus und anschließend das zugehörige Element (mit dem Array-Namen und dem Index in eckigen Klammern). document.write(index + ": " + a[index] + " ");
Hier das vollständige Skript: Listing 4.21: for-in (for_in.html)
for in <script language="JavaScript">
124
Es handelt sich hier tatsächlich um einen Operator. Allerdings ist dies keine für die Praxis wichtige Unterscheidung.
//--> Abbildung 4.22: Der Inhalt des Arrays wird ausgegeben.
while Die while-Schleife ist wesentlich einfacher aufgebaut als die for-Schleife. Einziger Parameter ist die Bedingung, die vor jedem Schleifendurchlauf überprüft wird. Tritt sie ein, werden die Anweisungen im Schleifenkörper ausgeführt: while (Bedingung) { Anweisungen; }
Dennoch können Sie, wie der folgende Code beweist, mit while dieselben Aufgaben wie mit einer for-Schleife bewältigen: while <script language="JavaScript">
KOMPENDIUM
JavaScript
125
Kapitel 4
Programmieren
Abbildung 4.23: Mit der whileSchleife lassen sich dieselben Aufgaben erledigen wie mit for.
Dieser Code gibt die Quadrate der Zahlen von 1 bis 10 aus (siehe analog Listing 4.15). Gegenüber der for-Schleife muss die Zählervariable allerdings bereits außerhalb der Schleife definiert und im Schleifenkörper bei jedem Durchlauf hochgezählt werden. Die Syntax für eine while-Schleife mit Zähler sieht also wie folgt aus: Zählerinitialisierung while (Bedingung) { Anweisungen; Zähleränderung }
Wann ist while sinnvoller? Welche Schleife Sie zu welchem Zweck einsetzen, ist im Prinzip Geschmacksache. Erfolgt die Überprüfung der Bedingung nicht direkt in den Parametern der Schleife, sondern in einer if-Anweisung, wird oft die while-Schleife bevorzugt. Folgendes Beispiel arbeitet mit einer while-Schleife, die erst abgebrochen wird, wenn die if-Bedingung erfüllt und eine durch 21 teilbare Zahl unter 100 gefunden wurde:
126
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
while besser als for? <script language="JavaScript">
Listing 4.23: Ist while manchmal besser als for? (while_besser.html)
while (weiter == true) { if (zahl % 21 == 0) { document.write(zahl + " ist durch 21 teilbar"); weiter = false; } zahl--; }
//-->
Auch dieses Beispiel lässt sich natürlich mit einer for-Schleife realisieren. Hier ist die while-Schleife ohne die zwei zusätzlichen Parameter jedoch praktischer, da in einer for-Schleife die Bedingung nicht mit den Zählervariablen übereinstimmen würde: for (var zahl = 100; weiter == true; zahl--) {
ist für das Verständnis nicht sehr sinnvoll. Die while-Schleife im letzten Beispiel ließe sich auch noch einfacher gestalten, indem die Bedingung auf true gesetzt und in der if-Anweisung break verwendet würde: while (true) { if (zahl % 21 == 0) { document.write(zahl + " ist durch 21 teilbar"); break; } zahl--; }
Dies funktioniert zwar identisch, balanciert allerdings noch näher an der Endlosschleife, da die Bedingung nie false werden kann.
KOMPENDIUM
JavaScript
127
Kapitel 4
Programmieren
Abbildung 4.24: Die erste durch 21 teilbare Zahl wurde gefunden und ausgegeben.
do while Die do while-Schleife überprüft die Bedingung erst am Ende: do { Anweisungen; } while (Bedingung)
Das heißt auch, dass die Anweisungen im Schleifenkörper mindestens einmal ausgeführt werden, unabhängig davon, ob die Bedingung am Anfang erfüllt oder nicht erfüllt ist. do while gehört noch nicht seit den Anfängen zu JavaScript wie die anderen Schleifen. Netscape 2 und 3 und Internet Explorer 3 in beiden Varianten unterstützen sie nicht. Aus heutiger Sicht werden allerdings alle aktuellen und wichtigen Browser unterstützt. Tabelle 4.10: do while-Schleife
128
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Schleifen
Kapitel 4
Ein Beispiel verdeutlicht die Besonderheit der do while-Schleife: do while-Schleife <script language="JavaScript">
Die Bedingung i <= 10 ist nicht erfüllt. Dennoch werden die Anweisungen im Schleifenkörper einmal ausgeführt und das Quadrat von 11 ausgegeben. Abbildung 4.25: 11*11 wurde ausgegeben, obwohl die Bedingung i <= 10 nicht erfüllt ist.
KOMPENDIUM
JavaScript
129
5
Funktionen
Eine Funktion besteht aus einer oder mehreren Anweisungen. Die Funktion wird mit ihrem Namen aufgerufen. Ein Funktionsaufruf kann beispielsweise an ein Ereignis oder einen Event-Handler gekoppelt sein. In JavaScript lassen sich eigene Funktionen definieren und einige vorgefertigte Funktionen nutzen. Warum aber sollte ein Programmierer Funktionen definieren, wenn er die Anweisungen auch einfach untereinander schreiben kann? Funktionen haben den Vorteil, dass sie aus einer beliebigen Stelle des Skripts – auch mehrmals – verwendet werden können. Außerdem strukturieren sie den Code und machen ihn übersichtlicher.
5.1
Eigene Funktionen
Eine eigene Funktion ist schnell geschrieben. Sie beginnt immer mit dem Schlüsselwort function, dann folgt der Funktionsname. Die Anweisungen befinden sich in einem Block, der von geschweiften Klammern umgeben ist. function Name() { Anweisungen; }
Um die Funktion aufzurufen, genügt der Name mit runden Klammern dahinter: Name();
Einige ältere Browser mögen es nicht, wenn Funktionen aufgerufen werden, bevor sie definiert wurden. In neueren Browsern ist dies zwar kein Problem, es ist jedoch besser, Funktionen erst zu definieren und dann aufzurufen. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Tabelle 5.1: Funktion erst aufrufen und anschließend definieren.
131
Kapitel 5
Funktionen Am besten sammeln Sie Funktionen im Kopf der HTML-Seite, damit Sie einen besseren Überblick haben. Funktionen lassen sich ebenfalls hervorragend dazu verwenden, um Code zu strukturieren. Das folgende einfache Beispiel ruft eine Funktion auf, die einen Text ausgibt:
Listing 5.1: Eine sehr einfache Funktion (funktion.html)
Eine simple Funktion <script language="JavaScript">
//--> Abbildung 5.1: Die Funktion gibt Text aus.
Sehr häufig werden Funktionen in Event-Handlern aufgerufen. EventHandler stehen als Attribute in HTML-Tags: Listing 5.2: Eine Funktion im Event-Handler onclick aufrufen (funktion_eventhandler.html)
Funktion und Event-Handler <script language="JavaScript">
//-->
Wird in eval() ein Objekt ausgewertet, gibt eval() eine Verknüpfung auf das Objekt zurück.
KOMPENDIUM
JavaScript
151
Kapitel 5
Funktionen
Abbildung 5.19: Der Nutzer gibt JavaScript-Code im Textfeld ein. Beim Anklicken der Schaltfläche wird der Code ausgewertet und das Ergebnis ausgegeben.
eval("window");
ist also eine Verknüpfung auf das window-Objekt. Folgender Code gibt alle Eigenschaften des window-Objekts zurück: Listing 5.19: Objektverknüpfung mit eval() (eval_rueckgabe. html)
eval() mit Rückgabe <script language="JavaScript">"); } //-->
Eine Alternative zu eval() ist die Methode execScript(String, Sprache). Sie ist eine Methode des window-Objekts (siehe Kapitel 6 »Objekte«) und kann Code in verschiedenen Sprachen ausführen. Mögliche Parameter für die Sprache sind JavaScript, JScript und VBScript. Insbesondere, wenn Sie Code in einer anderen Sprache, beispielsweise VBScript, ausführen möchten, ist diese Methode hilfreich. Im Gegensatz zu eval() liefert sie nichts zurück. Allerdings bleibt sie auf den Internet Explorer beschränkt.
152
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5 Abbildung 5.20: Eigenschaften des window-Objekts
URLs Eine URL (Uniform Resource Locator) in der Adressleiste des Browsers wird nicht in normaler Schreibweise dargestellt. Leerzeichen entsprechen beispielsweise dem Hexadezimalcode %20. Daher müssen Sie, wenn Sie in JavaScript mit URLs arbeiten, diese erst umwandeln. Die Schreibweise für URLs heißt URI-Codierung (Encoding). URI steht für Uniform Resource Identifier. Die Funktion escape(String) wandelt eine normale Zeichenkette in URICodierung um. escape() <script language="JavaScript"> Abbildung 5.21: Die URL wurde umgewandelt.
escape(String) codiert alle alphanumerischen Zeichen außer dem Plus-Symbol (+), da dies als Symbol für URLs bei Suchanfragen dient. unescape(URL) sorgt für die Rückumwandlung einer URL in eine Zeichen-
kette. Listing 5.21: unescape()
var x = unescape("http%3A//www.mut.de/JS%20Buch/"); document.write(x);
(Ausschnitt aus: unescape.html) Abbildung 5.22: Die URL ist wieder ein normaler String.
Neue Funktionen In neueren Browsern2 gibt es vier neue Funktionen zum Codieren und Decodieren von URLs. Der Grund für die neuen Funktionen war, dass escape()außer dem Pluszeichen (+) alle alphanumerischen Zeichen codiert. In der URI sind allerdings mittlerweile3 auch einige andere Zeichen wie bei2 3
154
und offiziell im ECMA-262-Standard v3 Grundlage ist die neue Regelung des URI-Standards der IETF RFC2396 (http://www.ietf.org/rfc/rfc2396.txt).
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5
spielsweise das Fragezeichen (?) zum Abtrennen von Daten bei der Übertragung mit GET in serverseitigen Programmiersprachen erlaubt. Die neuen Funktionen wandeln diese Zeichen nicht um. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das direkte Pendant zu escape() bildet encodeURI(). Es arbeitet wie escape(), wandelt allerdings folgende Zeichen nicht um: ?
;
/
:
@
&
=
+
$
,
-
_
.
!
~
*
'
(
)
#
Tabelle 5.5: encodeURI, decodeURI(), encodeURIComponent () und decodeURIComponent()
Tabelle 5.6: Von encodeURI() nicht umgewandelte Zeichen
Für die Rückumwandlung wird statt unescape() einfach decodeURI() eingesetzt. Im folgenden Beispiel wird ein String in eine URL umgewandelt, ausgegeben, rückumgewandelt und wieder ausgegeben: encodeURI() und decodeURI() <script language="JavaScript">"); var x = decodeURI(x); document.write(x); //-->
Listing 5.22: encodeURI() und decodeURI() im
Einsatz (encodeURI_decode URI.html)
Die
zwei Funktionen encodeURIComponent(String) und decodeURIComponent(String) sind Varianten von encodeURI(String) und decodeURI(String). Sie
dienen dazu, nur einzelne Teile einer URL zu codieren. Daher codieren sie auch die von encodeURI() ausgelassenen Zeichen (auch das Pluszeichen (+)) und sollten auch nicht für komplette URLs eingesetzt werden.
KOMPENDIUM
JavaScript
155
Kapitel 5
Funktionen
Abbildung 5.23: Codiert und decodiert
Das vorhergehende Beispiel sieht für die encodeURIComponent(String) und decodeURIComponent(String) wie folgt aus: Listing 5.23: Stärkere Codierung (components.html)
var x = encodeURIComponent("http://www.mut.de/JS Buch/ test.html?autor=hauser"); document.write(x + " "); var x = decodeURIComponent(x); document.write(x);
In Abbildung 5.24 sehen Sie, dass alle alphanumerischen Zeichen in der URL codiert werden. Abbildung 5.24: encodeURIComponent() codiert die
URL wesentlich stärker.
Debugging Die Funktionen watch(Eigenschaft, Debugger) und unwatch(Eigenschaft) dienen dazu, die Veränderung von Eigenschaften zu kontrollieren. Sie sind Anweisungen für einen externen Debugger wie beispielsweise den JavaScript Debugger von Mozilla und Netscape. watch() gibt dem Debugger an, dass er die Eigenschaft beobachten soll. unwatch() hebt die Beobachtung auf.
156
KOMPENDIUM
JavaScript
Globale Funktionen
Kapitel 5
Allerdings gibt es effektivere Wege des Debuggings und die Funktionen sind auf den Netscape Navigator und Mozilla beschränkt. Mehr zu diesem Thema finden Sie in Kapitel 9 »Debugging«. NS4.x NS6
NS7
watch
unwatch
KOMPENDIUM
JavaScript
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 5.7: watch und unwatch()
157
6
Objekte
Alle modernen Programmiersprachen schmücken sich heute mit Objekten und gerne auch mit dem Prädikat »objektorientiert«. JavaScript bildet da keine Ausnahme, ist allerdings ein wenig bescheidener. JavaScript wird als objektbasiert bezeichnet. Dies ist eine Stufe unter der reinen Objektorientierung, wie sie beispielsweise Java besitzt. Da die klassenbasierte Vererbung und die strenge Typisierung von Datentypen in JavaScript fehlen, reicht es nur zur objektbasierten Programmiersprache. In der Praxis lässt sich mit JavaScript dennoch sehr gut objektorientiert programmieren (siehe Kapitel 8 »OOP«). Beispielsweise bietet JavaScript statt der klassenbasierten Vererbung die Prototyp-basierte. Natürlich können Sie mit JavaScript auch rein prozedurale – also ablauforientierte – Skripten schreiben. Insbesondere bei den kürzeren Skripten im Web ist das sogar wesentlich häufiger anzutreffen. Prozedural bedeutet, dass das Skript nach einem bestimmten Schema abläuft: Fallunterscheidungen und Schleifen bestimmen den Ablauf und mit Funktionen können häufige Anweisungen zentral verwaltet werden. Aber auch wenn Sie prozedural programmieren, verwenden Sie Objekte. Zwar programmieren Sie keine eigenen, aber viele (nahezu alle) Möglichkeiten von JavaScript werden in Objekten zur Verfügung gestellt. Denken Sie nur an die Anweisung document.write() zur Ausgabe. document ist eines der wichtigsten JavaScript-Objekte, write() eine Methode dieses Objekts. Im folgenden Abschnitt erhalten Sie eine Antwort auf die Frage, was Objekte eigentlich sind und was mit Objektorientierung gemeint ist. Sollten Sie in diesem Bereich bereits fit sein, überblättern Sie den Abschnitt. Anschließend werden die wichtigsten eingebauten Objekte von JavaScript kurz vorgestellt. Einigen Objekten, beispielsweise Date, Math und String ist in diesem Kapitel mehr Raum gewidmet, andere – vor allem die Objekte zur Interaktion mit dem Browser – finden Sie in vielen Kapiteln des zweiten Teils dieses Buches (»Webanwendungen«) ausführlich mit Beispielen illustriert.
KOMPENDIUM
JavaScript
159
Kapitel 6
Objekte
6.1
Was sind Objekte?
Die Objektorientierung scheint erst einmal ein sehr abstraktes Thema zu sein. Das ist – salopp ausgedrückt – eigentlich Unsinn. Insbesondere im Konkreten, Realen, leicht Vorstellbaren liegt die Stärke der Objektorientierung. Stellen Sie sich ein reales Objekt vor, beispielsweise einen Vogel. Einen Vogel komplett in die Programmierung umzusetzen ist schwierig, eigentlich sogar unmöglich. Selbst ein 3D-Bild kann beispielsweise sein Verhalten nicht einfangen. In der Objektorientierung bleibt die Betrachtung abstrakter. Einige Eigenschaften legen fest, um welchen Vogel es sich handelt. Die Art legt beispielsweise seine Rasse fest, die Eigenschaft Laut legt fest, welche Laute ein Vogel von sich geben kann. Damit der Vogel auch etwas tut, werden für ihn Methoden programmiert. Beispielsweise die Methode Fressen, damit er Körner picken kann. Die Methode Laut geben könnte die Eigenschaft Laut ausgeben. Abbildung 6.1: Ein Vogel kann mit einfachen Mitteln – hier zwei Eigenschaften und zwei Methoden – bereits einiges anfangen.
Vogel Art Laut Laut geben Fressen Führt man die vier soeben beschriebenen Eigenschaften und Methoden in einem einfachen Diagramm zusammen, ergibt sich bereits eine Struktur, wie das Objekt Vogel in der Programmierung aussehen könnte (siehe Abbildung 6.1). Diese Struktur nennt man in der objektorientierten Programmierung Klasse. Die Klasse Vogel bildet also das Schema für alle Objekte. Jeder einzelne Vogel hat die Struktur der übergeordneten Klasse. Ein Vogel namens Kra hat beispielsweise die Art Papagei und gibt den Laut Kra von sich. Ein anderer Vogel heißt dagegen beispielsweise Wuschl, hat die Art Meise und den Laut Tschiep (siehe Abbildung 6.2).
160
KOMPENDIUM
JavaScript
Was sind Objekte?
Kapitel 6
Kein Objekt ist gleich, auch wenn es dieselben Eigenschaften und dieselbe Objektbezeichnung hat. Dieses Prinzip heißt Objektidentität. Es ist sinnvoll, da es einen Papagei Kra sowohl in einem Käfig in Los Angeles als auch in einem Zoo in Tokio geben könnte. Abbildung 6.2: So können Objekte und ihre Klasse notiert werden.
Vogel Art
Klasse
Laut Laut geben Fressen Instanz von
Kra:Vogel Objekte
Instanz von
Wuschl:Vogel
Art = Papagei
Art = Meise
Laut = Kra
Laut = Tschiep
Laut geben Fressen
Laut geben Fressen
Ein Objekt ist eine Instanz einer Klasse. Das Erzeugen eines Objekts heißt auch instanziieren. Kra ist also beispielsweise eine Instanz der Klasse Vogel. In JavaScript wird ein Objekt mit dem Schlüsselwort new instanziiert. Das Schlüsselwort new heißt auch Konstruktor. var x = new String("Text");
Diese Zeile instanziiert beispielsweise ein String-Objekt. Bei eigenen Objekten müssen Sie in JavaScript vorher selbst die Struktur anlegen (siehe Kapitel 8 »OOP«). Das String-Objekt ist dagegen in JavaScript bereits als Klasse vorhanden. Die bereits in JavaScript vorhandenen Klassen werden meist als Objekte bezeichnet. Hier verschwimmen die Begriffe. Der Kontext verrät allerdings, ob es sich um die Instanz oder um das übergeordnete Objekt (die Klasse) handelt.
Eigenschaften Wenn Sie ein neues String-Objekt instanziieren, erhält es automatisch alle Eigenschaften und Methoden der Klasse String – wie auch ein Objekt von der Klasse Vogel alle Eigenschaften und Methoden erhält (siehe Abbildung 6.2).
KOMPENDIUM
JavaScript
161
Kapitel 6
Objekte Auf Eigenschaften zugreifen Um auf die Eigenschaft eines Objekts zuzugreifen, schreiben Sie den Objektnamen (auch Objektbezeichner) und nach einem Punkt1 die Eigenschaft: document.write(x.length);
gibt die Länge des String-Objekts x aus. Da es als Zeichenkette »Text« enthält, gibt der Interpreter 4 Zeichen als Länge aus (siehe Abbildung 6.3). Abbildung 6.3: Das String-Objekt hat eine Länge von 4 Zeichen.
Eigenschaften ändern Die meisten Eigenschaften von vorgegebenen Objekten können nur gelesen werden. Einige Eigenschaften lassen sich allerdings auch ändern. Ein Beispiel ist das location-Objekt. Es hat eine Eigenschaft href, die die URL (Uniform Resource Locator) der aktuellen Seite enthält. Wenn Sie diese Eigenschaft setzen, leitet der Browser auf die neue URL um: window.location.href="http://www.mut.de";
Dieser Code leitet also auf die Homepage von Markt+Technik um. Vor location.href ist das Objekt window notiert. Der Grund ist, dass location ein Unterobjekt von window ist. Mehr dazu erfahren Sie im Abschnitt »Vererbung«.
Methoden Methoden eines Objekts führen etwas aus. Daher haben Methoden Ähnlichkeiten mit Funktionen. Allerdings sind Methoden immer an ein Objekt gebunden. Das String-Objekt hat beispielsweise sehr viele Methoden. Eine davon, die Methode big(), legt automatisch die HTML-Tags und big> um den Text, damit er größer hervorgehoben wird.
1
162
Der Punkt ist ein Operator. Der Operand links vom Punkt ist eine Referenz auf das Objekt, der Operand rechts die Eigenschaft oder Methode.
KOMPENDIUM
JavaScript
Was sind Objekte?
Kapitel 6
var x = new String("Text"); document.write(x.big()); Abbildung 6.4: Der Text wird mit der Methode big() größer dargestellt.
Parameter übergeben Methoden werden in JavaScript wie Funktionen mit runden Klammern abgeschlossen. Eine weitere Parallele zu Funktionen ist, dass in den runden Klammern Parameter übergeben werden dürfen. Die Methode link(URL) des String-Objekts versieht beispielsweise einen String mit einem Link auf eine Webadresse, die als Parameter angegeben sein muss: Methode mit Parameter <script language="JavaScript">
Listing 6.1: Eine Methode mit Parameter (methode_parameter.html)
Abbildung 6.5: Der funktionierende Link wurde mit einer Methode des String-Objekts erzeugt.
KOMPENDIUM
JavaScript
163
Kapitel 6
Objekte
Vererbung Das Konzept der Vererbung ist eine der Stärken der Objektorientierung. Eine Klasse kann von einer anderen Klasse ihre Eigenschaften und Methoden erben. Sie ist dann eine Unterklasse. Abbildung 6.6 zeigt das Prinzip: Die Art des Vogels ist hier keine Eigenschaft mehr, sondern eine eigene Klasse. Dadurch können bestimmte Vogelrassen andere Eigenschaften und Methoden haben als andere. Der Papagei kann beispielsweise auch Sprechen, die Meise nicht. Ein instanziiertes Objekt der Klasse Papagei, hier also Kra, übernimmt die Methode Sprechen aus der Struktur seiner Klasse Papagei. Die Eigenschaften und Methoden Laut, Laut geben und Fressen übernimmt er von der übergeordneten Klasse Vogel. Abbildung 6.6: Das Prinzip der Vererbung
Vogel Laut Laut geben Fressen erbt von
Papagei
erbt von
Meise Vorkommen
Sprechen
Instanz von
Kra:Papagei Laut = Kra
Instanz von
Wuschl:Meise Laut = Tschiep Vorkommen = Europa
Laut geben Fressen Sprechen
164
Laut geben Fressen
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Sie haben die Vererbung bereits bei einem in JavaScript integrierten Objekt2 gesehen. Das Objekt location ist ein Unterobjekt von window. Das windowObjekt ist noch viel mehr: Es ist das übergeordnete Objekt für alle Objekte, die in einem Browserfenster und damit auf einer Webseite vorkommen. Für eigene Objekte bietet JavaScript die prototype-basierte Vererbung. Mehr dazu finden Sie in Kapitel 8 »OOP«.
Polymorphismus Wenn eine Methode in zwei Klassen verschiedene Funktionen hat, nennt man dies Polymorphismus. Ein Beispiel ist der Aufruf der Methode braten. Ein Objekt der Klasse Mensch macht dann den Herd warm. Ein Objekt der Klasse Vogel sollte dagegen schleunigst das Weite suchen.
6.2
Objekte von JavaScript
JavaScript stellt eine Reihe von Objekten zur Verfügung. Mit diesen Objekten arbeiten Sie. Die Sprachsyntax, die die Kapitel 3 bis 5 dieses Buches füllt, ist nur ein Hilfsmittel, um mit den vielen Objekten von JavaScript etwas anfangen zu können. JavaScript besitzt verschiedenartige Objekte, die auch unterschiedliche Aufgaben erfüllen. Alle Objekte von JavaScript lassen sich grob in drei Kategorien unterteilen: Browserobjekte – alle Objekte, die in Verbindung mit dem Browserfenster und dem Inhalt des Browsers stehen. Über diese Objekte wird der größte Teil der Arbeit in JavaScript bewältigt. Da diese Objekte Browserspezifisch sind, gibt es zwischen den Browsern natürlich einige Unterschiede, die Sie bei der Beschreibung der einzelnen Objekte finden. Abbildung 6.7 gibt einen Überblick über wichtige Browserobjekte. Die hier abgebildete Hierarchie heißt auch DOM (Document Object Model). Jeder Browser besitzt sein eigenes DOM. Allerdings wird vom W3C auch ein DOM standardisiert. Mehr zu diesem Thema erfahren Sie in Kapitel 10 »Document Object Model«. Die verschiedenen Browserobjekte finden Sie insbesondere im zweiten Teil dieses Buches (»Webanwendungen«), denn sie bilden die Grundlage zur Arbeit mit JavaScript. Ohne Browserobjekte wäre der Zugriff auf Frames und Formulare nicht möglich. Sie könnten mit JavaScript keine neuen Fenster öffnen und noch nicht einmal mit document.write() Text ausgeben. 2
Hier ist mit Objekt nicht das instanziierte Objekt, sondern die Klasse gemeint.
KOMPENDIUM
JavaScript
165
Kapitel 6
Objekte
Abbildung 6.7: Ein einfaches DOM der Browserobjekte
window document form
link
frame
history
location
navigator
...
Die Browserobjekte sind kein Teil des JavaScript-Interpreters, sondern werden vom Browser auch anderen Skriptsprachen wie beispielsweise VBScript im Internet Explorer zur Verfügung gestellt. Der JavaScript-Interpreter beinhaltet nur die Schnittstelle zu diesen Objekten und damit zum DOM. Eingebaute Standardobjekte3 – sind Teil des ECMAScript-Standards v3 und von JavaScript 1.5. Sie werden daher von den neueren Browsern unterstützt. Inkompatibilitäten und Probleme finden Sie bei den detaillierteren Beschreibungen der Objekte. – Array – enthält Eigenschaften und Methoden für Arrays. Arrays werden in Kapitel 7 »Arrays und Strings« genauer beleuchtet. – Boolean – enthält die Wahrheitswerte (siehe in diesem Kapitel Abschnitt »Boolean«). – Date – dient zur Arbeit mit Daten und Uhrzeit. Eine Beschreibung finden Sie im Abschnitt »Date«. – Function – ist das Objekt für Funktionen. Es wird in Kapitel 8 »OOP« erläutert. – Math – enthält mathematische Funktionen und Konstanten. Wie Sie damit rechnen, erfahren Sie im Abschnitt »Math«. – Number – dient zur Arbeit mit dem Datentyp Zahl (siehe Abschnitt »Number«). – Object – steht für den Datentyp Object bereit (siehe Kapitel 8 »OOP«). – RegExp – erlaubt reguläre Ausdrücke in JavaScript. Sie werden in Kapitel 16 »Formulare« behandelt. – String – ermöglicht die Arbeit mit Zeichenketten. Dieses Objekt ist Teil von Kapitel 7 »Arrays und Strings«. Browser-spezifische eingebaute Objekte – sind alle Objekte, die keine Browserobjekte und nicht Teil des Standards sind. Eine Beschreibung dieser Objekte finden Sie im Abschnitt »Browser-spezifische Objekte«. 3
166
In Unterscheidung zu den Browserobjekten werden sie auch häufig Standardklassen genannt.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Math Das Math-Objekt beinhaltet mathematische Konstanten und Funktionen. Die Konstanten sind natürlich Eigenschaften, die Funktionen dagegen Methoden, da sie etwas ausführen. Das Math-Objekt muss nicht mit new instanziiert werden. Es kann direkt aufgerufen werden und steht immer zur Verfügung. Tabelle 6.2 und Tabelle 6.3 zeigen die Eigenschaften und Methoden des Math-Objekts im Überblick. Anschließend finden Sie Erklärungen und Beispiele zum Rechnen, Runden und zu Zufallszahlen. Das Math-Objekt und seine Eigenschaften und Methoden werden in allen gängigen Browsern unterstützt und sind bereits ab JavaScript 1.0 vorhanden. NS4.x NS6
NS7
IE4
IE5
IE5.5 IE6
O7
M1
K3
Math
Eigenschaft
Beschreibung
Wert
E
die Konstante e (eulersche Zahl)
2.718281828459045
LN2
der natürliche Logarithmus von 2
0.6931471805599453
LN10
der natürliche Logarithmus von 10
2.302585092994046
LOG2E
der Logarithmus von e zur Basis 2
1.4426950408889633
LOG10E
der Logarithmus von e zur Basis 10
0.4342944819032518
PI
die Kreiszahl ð (gesprochen PI)
3.141592653589793
SQRT1_2
Quadratwurzel von ½
0.7071067811865476
SQRT2
Quadratwurzel von 2
1.4142135623730951
Tabelle 6.1: Das Math-Objekt
Tabelle 6.2: Die Eigenschaften des Math-Objekts
Die Tabelle enthält die Genauigkeit, in der JavaScript die mathematischen Konstanten speichert und für Berechnungen zur Verfügung stellt. Auf der CD-ROM finden Sie die Datei math_eigenschaften.html, in der alle Eigenschaften ausgegeben werden.
KOMPENDIUM
JavaScript
167
Kapitel 6 Tabelle 6.3: Die Methoden des Math-Objekts
168
Objekte
Methode
Beschreibung
Beispiel
abs(Zahl)
Absolutwert einer Zahl
x = Math.abs(-4); //Erg: 4
acos(Zahl)
Arkuskosinus einer Zahl
x = Math.acos(0.4); //Erg: 1.1592794807274085
asin(Zahl)
Arkussinus einer Zahl
x = Math.asin(1); //Erg: 1.5707963267948965
atan(Zahl)
Arkustangens einer Zahl
x = Math.atan(2); //Erg: 1.1071487177940904
atan2(Gegenkathete, Ankathete)
Arkustangens der PolarKoordinaten der Gegenkathete und Ankathete
x = Math.atan2(2,3); //Erg: 0.5880026035475675
ceil(Zahl)
nächster ganzzahliger Wert, x = Math.ceil(4.3); //Erg: 5 der größer oder gleich der angegebenen Zahl ist
cos(Zahl)
Kosinus einer Zahl
exp(Zahl)
eZahl; die Zahl als Potenz der x = Math.exp(2); //Erg: 7.38905609893065 eulerschen Zahl
floor(Zahl)
nächster ganzzahliger Wert, x = Math.floor(4.3); //Erg: 4 der kleiner oder gleich der angegebenen Zahl ist
log(Zahl)
natürlicher Logarithmus der x = Math.log(10); // Erg: Zahl; ein natürlicher Loga- 2.302585092994046 rithmus hat die Basis e, also die eulersche Zahl.
max(Zahl1, Zahl2)
liefert die größere der beiden Zahlen
x = Math.max(4, 3); //Erg: 4
min(Zahl1, Zahl2)
liefert die kleinere der beiden Zahlen
x = Math.min(4, 3); //Erg: 3
pow(Zahl, Potenz)
ZahlPotenz; liefert als Ergebnis eine potenzierte Zahl
x = Math.pow(2, 3); //Erg: 8
random()
ergibt eine Zufallszahl zwischen 0 und 1 (siehe Abschnitt »Zufallszahlen«)
x = Math.random;
x = Math.cos(-1); //Erg: 0.5403023058681398
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Methode
Beschreibung
Beispiel
round(Zahl)
x = Math.round(4.56); //Erg: 5 rundet eine Zahl auf die nächste ganze Zahl auf, wenn sie hinter dem Komma größer gleich .5 ist, ansonsten wird abgerundet (siehe Abschnitt »Runden«).
sin(Zahl)
Sinus einer Zahl
sqrt(Zahl)
Quadratwurzel (v) einer Zahl x = Math.sqrt(9); //Erg: 3
tan(Zahl)
Tangens einer Zahl
Tabelle 6.3: Die Methoden des Math-Objekts (Forts.)
var x = Math.sin(2); //Erg: 0.9092974268256817
x = Math.tan(0.4); //Erg: 0.4227932187381618
Bei einigen Funktionen sind manche Werte nicht erlaubt, beispielsweise müssen die Zahlen (im Bogenmaß) beim Arkuskosinus zwischen -1 und 1 liegen. Ist dies nicht der Fall, gibt der JavaScript-Interpreter als Ergebnis NaN zurück. Auf der CD-ROM zum Buch finden sie im Ordner code/kap6 alle Methoden des Math-Objekts als Beispieldatei. Der Dateiname entspricht dem Methodennamen, die Endung lautet .html. Rechnen Prinzipiell ist mit den mathematischen Methoden und den arithmetischen Operatoren im Zusammenspiel natürlich jede Art von mathematischer Berechnung möglich. Ein einfaches Beispiel zeigt ein mögliches Einsatzgebiet. Ein HTML-Formular nimmt in zwei Textfeldern zwei Werte auf. Klickt der Nutzer auf eine Schaltfläche, potenziert eine Funktion den ersten Wert (x) mit dem zweiten Wert (y). Rechnen <script language="JavaScript">
Listing 6.2: Eine Potenz ausrechnen (rechnen.html)
} //--> Abbildung 6.11: Die Umrechnung von Bogenmaß in einen Winkel funktioniert gewissermaßen »on the fly«.
172
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Runden Das Runden ist sehr einfach. Das folgende Skript rundet eine Zahl, die der Nutzer in ein Textfeld eingibt. Das Ergebnis landet in einem anderen Textfeld: Runden <script language="JavaScript"> Abbildung 6.12: JavaScript rundet die Zahl.
Bei negativen Zahlen wird -4,50 auf -4 aufgerundet und erst -4,51 auf -5 abgerundet. Vorsicht, das wird häufig falsch gemacht. Nachkommastellen runden Wollen Sie eine Zahl in den Nachkommastellen runden, müssen Sie den Dezimalpunkt erst um so viele Stellen nach links verschieben, wie Sie runden möchten. In wenigen Schritten lässt sich Listing 6.4 so anpassen, dass es auf zwei Stellen hinter dem Komma rundet: In der Funktion kommt eine neue Variable als Zwischenspeicher zum Einsatz. Dies erhöht die Übersichtlichkeit.
KOMPENDIUM
JavaScript
173
Kapitel 6
Objekte Der Variablen wird als Wert das gerundete Ergebnis der um zwei Stellen nach links verschobenen Zahl übergeben. Für die Verschiebung multipliziert das Skript einfach mit 100. var r = Math.round(feld.value * 100);
Nun muss die Verschiebung um zwei Stellen nach links rückgängig gemacht werden. Dazu dient die Division durch 100. r = r / 100;
Abschließend erhält das zweite Textfeld mit Namen erg den gerundeten Wert zugewiesen. document.formular.erg.value = r;
Der vollständige Code sieht wie folgt aus: Listing 6.5: Nachkommastellen runden (runden_nachkom ma.html)
Nachkommastellen runden <script language="JavaScript">
} //--> Abbildung 6.13: Das Rundungsskript rundet nun auf zwei Stellen hinter dem Komma.
174
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Ändern Sie einfach den Multiplikator, je nachdem auf wie viele Stellen Sie runden möchten. Wollen Sie auf drei Stellen hinter dem Komma runden, multiplizieren Sie beispielsweise mit 1.000. Soll bereits vor dem Dezimalpunkt gerundet werden, teilen Sie durch ein Vielfaches von 10. max() und min() Math.max() und Math.min() wurden in neueren Browsern verbessert. Sie können nun auch beliebig viele Zahlen miteinander vergleichen und die größte beziehungsweise kleinste herausfinden. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
max
min
Tabelle 6.4: Math.max() und Math.min()
Das folgende Beispiel gibt bei einem Vergleich aus drei Zahlen die größte aus. Zwei der Zahlen werden noch in der max()-Methode mit arithmetischen Operatoren (siehe Kapitel 4.1 »Operatoren«) aus Variablenwerten errechnet: max() mit mehreren Zahlen <script language="JavaScript">
Listing 6.6: max() mit mehreren Zahlen (max_neu.html)
var x = Math.max(5.2, b / a, a * 2);
document.write(x); //--> Abbildung 6.14: Das richtige Ergebnis ist die dritte Zahl (a * 2 = 6).
KOMPENDIUM
JavaScript
175
Kapitel 6
Objekte Zufallszahlen Eine Zufallszahl ist schnell erzeugt.
Listing 6.7: Eine Zufallsdatei ausgeben (zufall.html)
Zufall <script language="JavaScript">
document.write(x); //--> Abbildung 6.15: Eine Zufallszahl
Beliebige Zufallszahlen Die Zahlen von 0 bis 1 – dazu noch in einer Genauigkeit von 17 Stellen – sind zwar schön, für die meisten Fälle aber nicht ausreichend. Nehmen wir an, Sie brauchen die Zufallszahlen in einer beliebigen Spanne von x bis y, dann hilft folgende Formel: x + Math.random() * (y – x)
Sollen die Zufallszahlen nur ganze Zahlen sein, müssen Sie das Ergebnis nur noch runden. Im folgenden Beispiel verwenden wir eine Zufallszahl, um damit Bilder mit den Namen 1 bis 6 zufällig aufzurufen. Diese Bilder zeigen verschiedene Augenzahlen eines Würfels. Für das Beispiel finden Sie die benötigten Bilddateien mit den Augenzahlen des Würfels. Sie befinden sich im Ordner code\kap6 und heißen 1.jpg bis 6.jpg. Listing 6.8: JavaScript simuliert einen Würfel (wuerfel.html).
176
Würfeln
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
<script language="JavaScript">");
//--> Abbildung 6.16: Der Würfel zeigt eine 5.
Date Das Date-Objekt muss – im Gegensatz zu Math – immer mit new instanziiert werden. var datum = new Date();
Diese Zeile weist der Variablen datum das Date-Objekt und damit das aktuelle Datum und die aktuelle Zeit zu. Folgendes Skript gibt das Datum sofort aus: Datum <script language="JavaScript">
Abbildung 6.17: Das Datum in seiner ursprünglichen Form
Das aktuelle Datum und die aktuelle Zeit beziehen sich bei clientseitigem JavaScript natürlich immer auf den Client, das heißt den Rechner des Nutzers. Wenn der seine Zeit umgestellt hat4 oder in einer anderen Zeitzone lebt, erhält er auch eine andere Uhrzeit. Der lange Datumsstring aus Abbildung 6.17 ist nur in seltenen Fällen praktisch. Meist benötigen Sie einzelne Elemente des Datums. Diese Elemente erhalten Sie mit Methoden des Date-Objekts. Die Methode getDate() liefert beispielsweise den Tag des Monats. Dazu wird einer Variablen der Rückgabewert der Methode zugewiesen. Listing 6.10: Eine Methode von Date verwenden (getDate.html)
Tag des Monats <script language="JavaScript">
document.write(tag); //-->
Das Date-Objekt und die hier genannten Methoden sind in allen neueren Browsern vorhanden. Nur Netscape 2 und 3 besitzen manche Methoden nicht.
4
178
Dies ist über das Betriebssystem einfach möglich. Unter Windows ist ein Doppelklick auf die Uhr rechts unten ausreichend. Die Uhrzeit lässt sich im Textfeld ändern. Diese Funktion kann aber deaktiviert sein, wenn der Nutzer kein Administrator ist. Ebenso lässt sich die Uhrzeit in den meisten Linux-Fenstermanagern ändern. Am Mac befindet sich die Uhrzeit meist rechts oben.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6 Abbildung 6.18: getDate() gibt den Tag des Monats aus.
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 6.5: Das Date-Objekt
Einige neuere Methoden finden Sie im Abschnitt »Neue Methoden«. Die meistverwendeten Methoden des Date-Objekts dienen dazu, einen Bestandteil des Datums oder der Uhrzeit zu liefern. Sie beginnen – wie getDate() aus dem vorhergehenden Beispiel – mit get. Wie Sie in Abschnitt »Eigene Daten« erfahren werden, können Sie allerdings auch eigene Daten erstellen. Entsprechend gibt es zu jeder get-Methode eine Methode mit set, die den jeweiligen Datumsbestandteil festlegt. datum.setDate(13);
setzt den Tag im Monat also auf den 13ten. In Tabelle 6.6 finden Sie eine Beschreibung des Inhalts der jeweiligen getund set-Methoden. Denken Sie daran, dass get liefert und set festlegt. Methode (get)
Methode (set)
Beschreibung
getDate()
setDate(Wert)
Tag des Monats von 1 bis 31
getDay()
setDay(Wert)
Tag der Woche von 0 (Sonntag) bis 6 (Samstag)
getFullYear()
setFullYear(Wert)
Jahr mit vier Stellen
getHours()
setHours(Wert)
Stunden des Tages von 0 bis 23
getMilliseconds()
setMilliseconds(Wert)
Millisekunden seit dem 1.1.1970, 00:00:00 GMT (siehe Abschnitt »Mit Daten rechnen«)
getMinutes()
setMinutes(Wert)
Die Minuten der Stunde von 0 bis 59
KOMPENDIUM
JavaScript
Tabelle 6.6: Die Methoden des Date-Objekts
179
Kapitel 6 Tabelle 6.6: Die Methoden des Date-Objekts (Forts.)
Objekte
Methode (get)
Methode (set)
Beschreibung
getMonth()
setMonth(Wert)
Der Monat des Jahres von 0 bis 11
getSeconds()
setSeconds(Wert)
Die Sekunden der Minute von 0 bis 59
getTime()
setTime(Wert)
Die Zeit in Millisekunden seit dem 1.1.1970, 00:00:00 GMT liefert die Differenz der auf dem Client eingestellten Zeitzone zur GMT (Greenwich Mean Time). Für den deutschsprachigen Raum: +60 Minuten
getTimezoneOffset()
getUTCDate()
setUTCDate(Wert)
liefert den Tag des Monats nach UTC-Zeitzone (UTC entspricht GMT).
getUTCDay()
setUTCDay(Wert)
Tag der Woche von 0 (Sonntag) bis 6 (Samstag) nach UTC
getUTCFullYear()
setUTCFullYear(Wert)
Jahr mit vier Stellen nach UTC
getUTCHours()
setUTCHours(Wert)
Stunde des Tages von 0 bis 23 nach UTC
getUTCMilliseconds()
setUTCMilliseconds(Wert) Millisekunden seit dem 1.1.1970,
getUTCMinutes()
setUTCMinutes(Wert)
Minuten einer Stunde von 0 bis 59 nach UTC
getUTCMonth()
setUTCMonth(Wert)
Monat des Jahres von 0 bis 11 nach UTC
getUTCSeconds()
setUTCSeconds(Wert)
Sekunden einer Minute von 0 bis 59 nach UTC
getYear()
setYear(Wert)
Jahr als zweistelliger Wert
andere Methoden
Beschreibung
parse(Datum)
wandelt ein Datum in die Zahl der Millisekunden seit 1.1.1970, 00:00:00 GMT um. Wird ohne Date-Objekt eingesetzt:
00:00:00 GMT nach UTC
Date.parse(Datum)
toGMTString()
180
liefert einen String mit dem GMT-Datum. Aussehen und Inhalt sind abhängig vom Browser.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Methode (get)
Methode (set)
Beschreibung
toString()
wandelt Datum und Zeit auf dem Rechner des Nutzers in einen String um.
toUTCString()
wandelt Datum und Zeit in einen String nach UTC um.
liefert die Zahl der Millisekunden zwischen dem 1.1.1970, 00:00:00 UTC und dem als Parameter übergebenen Datum. Die drei Datenkomponenten am Anfang sind verpflichtend, die Zeitkomponenten optional.
valueOf()
liefert das Datum als String nach UTC.
Tabelle 6.6: Die Methoden des Date-Objekts (Forts.)
Achten Sie bei den Datenwerten darauf, dass einige Werte, beispielsweise Tage der Woche (getDay()) oder Stunden des Tages (getHours()) bei 0 zu zählen beginnen. Im Abschnitt »Sommerzeit« finden Sie beschrieben, wie sich diese Werte in normale Daten umformatieren lassen. GMT und UTC Bei Daten ist immer von GMT und UTC die Rede. Was bedeutet dies eigentlich? GMT steht für Greenwich Mean Time, die nach dem Londoner Stadtteil Greenwich benannt ist und die Zeitzone mit der Standardzeit darstellt. Alle Zeitzonen östlich davon haben eine positive Zeitverschiebung, sind also Stunden voraus, alle westlich davon haben eine negative Zeitverschiebung. Der deutschsprachige Raum hat beispielsweise eine positive Zeitverschiebung um eine Stunde: +1 GMT. Abbildung 6.19: Die Zeitzone unter Windows XP
KOMPENDIUM
JavaScript
181
Kapitel 6
Objekte Die UTC-Zeit (Universal Time Coordinated) entspricht der GMT. UTC ist nur die neuere Bezeichnung. Zeitverschiebung Die Zeitverschiebung auf dem lokalen Rechner herauszufinden ist einfach; Dies erledigt die Methode getTimezoneOffset():
Listing 6.11: Zeitverschiebung mit getTimezoneOffset()
Aber Moment, das Ergebnis ist nicht so berauschend. -60 Minuten soll die Zeitverschiebung betragen (siehe Abbildung 6.20). Im deutschsprachigen Raum ist es aber doch +1 Stunde gegenüber UTC? Das Problem ist folgendes: Da die Methode die UTC intern von der lokalen Zeit abzieht, entsteht bei positiven Werten ein negativer Wert. Die Lösung ist nicht schwierig. Die Zeitverschiebung erhält einfach einen Vorzeichenwechsel. Des Weiteren werden die Minuten noch in Stunden umgerechnet: var datum = new Date(); var ver = -(datum.getTimezoneOffset()) / 60;
document.write(ver + " UTC");
182
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6 Abbildung 6.21: Nun sieht das Ergebnis wie erwartet aus.
Zeitverschiebung simulieren Die getTimezoneOffset()-Methode hat eine Schwäche. Sie kann nicht gesetzt werden. Wollen Sie also beispielsweise Stunde und Minute von New York und von Berlin ausgeben, erfordert dies etwas mehr Aufwand: Zeitverschiebung <script language="JavaScript">
Aber es geht auch etwas einfacher. Die folgende Schleife gibt alle Uhrzeiten in allen Zeitverschiebungen aus. Dies funktioniert wie folgt: Zuerst wird ein neues Date-Objekt mit dem aktuellen Datum instanziiert. var datum = new Date();
KOMPENDIUM
JavaScript
183
Kapitel 6
Objekte
Abbildung 6.22: Die Zeitverschiebung ausrechnen
In einer zweiten Variablen aktuell speichert das Skript die aktuelle Zeit in Millisekunden seit dem 1.1.1970, 00:00 GMT. Die Zeit in Millisekunden ist der Schlüssel zur Lösung des Umrechnungsproblems. Denn mit den Millisekunden zu einer festen Basis können Sie mit Daten rechnen (siehe Abschnitt »Mit Daten rechnen«)! var aktuell = datum.getTime();
Die dritte Variable nimmt die Zeitzonenverschiebung der aktuellen Zeit in Minuten auf. var zone = datum.getTimezoneOffset();
Das Herzstück des kleinen Programms ist die for-Schleife. Die Zählervariable läuft über die ganzen Zeitzonen von -12 bis +12. for (var i = -12; i < 13; i++) {
In der Schleife wird zuerst die Zeitzone (in Millisekunden5) von der aktuellen Zeit abgezogen. Anschließend wird die Zeitverschiebung (gespeichert in der Zählervariablen i) ebenfalls in Millisekunden6 dazugezählt. var erg = aktuell + zone * 60 * 1000 + i * 60 * 60 * 1000;
Ein neues Date-Objekt erhält den Zeitwert in Millisekunden. Daraus wird automatisch ein neues Datum gebildet. var time = new Date(erg);
5 6
184
Die Umrechnung von Minuten in Millisekunden lautet: Minuten * 60 * 1.000 = Millisekunden. Die Umrechnung von Stunden in Millisekunden lautet: Stunden * 60 * 60 * 1.000 = Millisekunden.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Als Nächstes geben wir Teile des Datums, hier Stunden und Minuten, aus. document.write(time.getHours() + ":" + time.getMinutes()); document.write(" " + i + " GMT "); }
Nachfolgend der vollständige Code: Zeitverschiebung <script language="JavaScript">"); } //-->
Listing 6.13: Die Zeitverschiebung in allen Zeitzonen (zeitverschiebung_ einfach.html)
Der Internet Explorer 3 liefert die Zeitverschiebung mit getTimezoneOffset() mit umgekehrtem Vorzeichen: für den deutschsprachigen Raum also +60 statt -60 (siehe Abbildung 6.23). Wollen Sie hier einen Fehler in der Rechnung vermeiden, müssen Sie eigens auf den Internet Explorer 3 prüfen. Eine entsprechende Prüfbedingung könnte wie folgt aussehen: navigator.appVersion.indexOf('MSIE 3') != -1
Mehr zur Browserunterscheidung erfahren Sie in Kapitel 12 »Browserunterscheidung«. Eigene Daten Im letzten Beispiel (siehe Listing 6.13) gibt bereits ein Betrag in Millisekunden das Datum für ein neues Date-Objekt vor. Die Syntax dazu sieht folgendermaßen aus: var datum = new Date(Millisekunden);
KOMPENDIUM
JavaScript
185
Kapitel 6
Objekte
Abbildung 6.23: Die aktuelle Uhrzeit in allen Zeitzonen
Das Datum wird aus den Millisekunden seit dem 1.1.1970, 00:007 GMT errechnet. var datum = new Date(264290400000);
entspricht beispielsweise dem 18. April 1978. Sie haben aber noch eine andere Möglichkeit, ein eigenes Datum anzugeben. Zuerst wieder die Syntax: var datum = new Date(Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Millisekunden);
7
186
Dieser Zeitpunkt wird als Beginn der Unix-Epoche festgelegt. Das Datum in Millisekunden heißt seitdem auch Unix-Zeitstempel.
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Die Angaben von Jahr, Monat und Tag sind hier obligatorisch. Das Jahr muss vierstellig angegeben werden. Der Monat von 0 (Januar) bis 11 (Dezember) und der Tag von 1 bis 31. Optional sind die Angaben der Zeit. Wenn sie erfolgen, dann allerdings in der festgesetzten Reihenfolge. Sie können also nicht nur Sekunden angeben, aber keine Minuten und Stunden. Die Stunden werden von 0 (Mitternacht) bis 23 angegeben, die Minuten von 0 bis 59, die Sekunden ebenfalls von 0 bis 59 und die Millisekunden von 0 bis 999. var datum = new Date(1978, 3, 18); var datum2 = new Date(2001, 12, 6, 9, 30, 0);
In der oberen Zeile wird nur das Datum übergeben, die Zeit wird automatisch auf 00:00:00 Uhr gestellt. In der unteren Zeile ist auch eine Zeitangabe bis hin zu Sekunden, aber ohne Millisekunden vorhanden. Abbildung 6.24: Ohne Uhrzeitangabe (erste Zeile des Codes) stellt der Interpreter die Uhrzeit auf 00:00:00.
Das Jahr-2000-Problem Das Jahr-2000-Problem8 haben viele bereits abgehakt. War ja alles nicht so schlimm … Das stimmt zwar teilweise, allerdings gilt es nach wie vor, vorsichtig zu sein. In JavaScript gibt es die Methoden getYear() und setYear(). Sie arbeiten mit einer zweistelligen Jahreszahl. Das folgende Beispiel zeigt die Probleme: Jahr 2000 <script language="JavaScript">"); var datum2 = new Date(2002, 3, 4); 8
Listing 6.14: getYear() hat ein Jahr-2000-Problem (jahr2000.html).
auch Y2K genannt
KOMPENDIUM
JavaScript
187
Kapitel 6
Objekte document.write(datum2.getYear()); //-->
Der Internet Explorer behilft sich damit, alle Jahre über 2000 vierstellig auszugeben (siehe Abbildung 6.25). Abbildung 6.25: Der Internet Explorer 6 gibt das Jahr 2002 vierstellig aus.
Im Netscape Navigator 7 funktioniert diese Krücke nicht mehr (siehe Abbildung 6.26). Abbildung 6.26: Das Jahr 2002 verkommt zu 102.
Den besten Ausweg bei diesen Problemen bietet die Methode getFullYear(), die das Jahr vierstellig zurückgibt. In sehr alten Browsern, Netscape 2 und 3 und Internet Explorer 3 in der ersten Version, ist diese Methode allerdings noch nicht enthalten. In diesem Fall hilft nur eine Fallunterscheidung, die Sie am einfachsten in eine Funktion packen: Listing 6.15: Jahr-2000-Fallunterscheidung (jahr2000_faelle. html)
188
Jahr 2000 Fallunterscheidung
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
<script language="JavaScript"> 100 && jahr < 200) { return jahr + 1900; } else { return jahr; } }
var datum = new Date(1978, 4, 18); document.write(getJahr2000(datum) + " "); var datum2 = new Date(2002, 3, 4); document.write(getJahr2000(datum2)); //-->
Die Fallunterscheidung hat nur einen Haken. Liegt das Jahr zwischen 100 und 200, weil Sie beispielsweise über die römische Kaiserzeit schreiben, funktioniert die Fallunterscheidung nicht mehr. Abbildung 6.27: Auch Netscape 2 kommt jetzt mit den Daten zurecht.
Wenn Sie die if-Bedingung verändern, können Sie natürlich auch die Jahre vor 2000 vierstellig schreiben. Entfernen Sie dazu einfach die Bedingung jahr > 100. Wollen Sie die Jahre ab 2000 mit zweistelliger Endung9 angezeigt bekommen, ziehen Sie einfach 100 ab, statt 1900 dazuzuzählen. Allerdings müssen Sie noch einen zusätzlichen Fall für die neueren Internet Explorer (im Listing hervorgehoben) einfügen, da sie das Jahr vierstellig ausgeben:
9
Hier besteht natürlich Verwechslungsgefahr mit den Jahren 1900, 1901 usw. Andererseits wird eine zweistellige Jahreszahl häufig bei der Bezeichnung von Jahrgängen oder aktuellen Dokumenten wie Auftragsbestätigungen und Bestellungen benötigt. Sie automatisch in JavaScript zu generieren, ist also durchaus öfter notwendig.
KOMPENDIUM
JavaScript
189
Kapitel 6
Objekte function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr > 100 && jahr < 200) { return jahr - 100; } else if (jahr > 1999){ return jahr - 2000; } else { return jahr; } }
Soll das Jahr auch bei einstelligen Ziffern zweistellig sein, müssen Sie noch einen String hinzufügen. Dafür muss wieder eine if-Bedingung herhalten: Listing 6.16: Jahreszahlen zweistellig und IE-kompatibel (zweistellig_ie.html)
function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr > 100 && jahr < 200) { jahr -= 100; if (jahr < 10) { return "0" + jahr; } else { return jahr; }
} else if (jahr > 1999){ jahr -= 2000; if (jahr < 10) { return "0" + jahr; } else { return jahr; }
} else { return jahr; } } Abbildung 6.28: Auch im IE klappt es jetzt mit den zweistelligen Jahreszahlen.
Daten aus der Vergangenheit Sehr alte Browser unterstützen keine Daten vor dem 1.1.1970, 00:00:00 GMT. Dazu gehören der Netscape Navigator 2 und 3 sowie der Internet Explorer 3 in der ersten Version. Bei diesen Browsern können Sie ältere Daten also nicht als Date-Objekt speichern. 190
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Mit Daten rechnen Um mit Daten zu rechnen, müssen Sie sie immer in Millisekunden seit der Unix-Epoche, also seit dem ominösen 1.1.1970, 00:00:00 GMT, umrechnen. Dann funktioniert die Rechnung aber sehr einfach: Zuerst instanziieren Sie zwei Date-Objekte. var datum1 = new Date(1978, 3, 18); var datum2 = new Date(2001, 11, 6);
Anschließend ziehen Sie die mit getTime() in Millisekunden seit dem 1.1.1970 umgewandelten Datenwerte voneinander ab. var erg = datum2.getTime() - datum1.getTime();
Da das Ergebnis noch in Millisekunden vorliegt, wird es in Tage umgerechnet und abgerundet, damit ganze Tage herauskommen: erg = Math.floor(erg / (1000 * 60 * 60 * 24));
Abschließend gibt das Skript das Ergebnis aus: document.write(erg + " Tage"); Mit Datumswerten rechnen <script language="JavaScript"> Abbildung 6.29: Zwischen den zwei Daten liegen 8.634 Tage.
KOMPENDIUM
JavaScript
191
Kapitel 6
Objekte Wenn Sie bei zwei Datenwerten nicht wissen, welcher aktueller und damit größer und welcher älter (kleiner) ist, könnten Sie sich mit einer if-Fallunterscheidung behelfen. Noch einfacherer geht es allerdings mit den mathematischen Methoden Math.max() und Math.min(). Damit finden Sie zuerst heraus, welcher Datumswert (in Millisekunden) größer und welcher kleiner ist. Anschließend wird der kleinere Wert vom größeren abgezogen.
Listing 6.18: Dieses Skript findet automatisch heraus, welches Datum aktueller ist (datum_vergleich. html).
var datum1 = new Date(1978, 4, 18); var datum2 = new Date(2001, 12, 6); var gr = Math.max(datum1.getTime(), datum2.getTime()); var kl = Math.min(datum1.getTime(), datum2.getTime());
Sommerzeit Die Sommerzeit lässt sich einfach einrechnen. Addieren Sie einfach eine Stunde hinzu. Am einfachsten erfolgt dies wieder in Millisekunden: zeit + 60 * 60 * 1000
Auf die Uhrzeit reagieren Wenn eine Webseite immer gleich aussieht, besucht der Nutzer sie sehr wahrscheinlich kein drittes Mal. Das Wichtigste, um Nutzer dauerhaft zu binden, ist natürlich der Inhalt. Aber auch optische Veränderungen können sehr reizvoll sein. Beispielsweise könnten Sie spontan auf die Uhrzeit reagieren. Das folgende Skript ändert das Hintergrundbild, je nachdem, ob es gerade Tag oder Nacht ist. Die Uhrzeit wird aus einem Date-Objekt mit getHours() ausgelesen. Eine Fallunterscheidung überprüft, ob es nach 7 und vor 20 Uhr noch Tag ist. In diesem Fall wird das Hintergrundbild tag.jpg verwendet, ansonsten (im else-Fall) das Hintergrundbild nacht.jpg. Die Beispielbilder zum Skript finden Sie auf der CD-ROM im Verzeichnis code\kap06. Sie heißen, wie im Skript zu sehen, tag.jpg und nacht.jpg.
192
KOMPENDIUM
JavaScript
Objekte von JavaScript Auf die Uhrzeit reagieren <script language="JavaScript"> 7 && datum.getHours() < 20) { document.body.background = "tag.jpg"; } else { document.body.background = "nacht.jpg"; } } //-->
Kapitel 6 Listing 6.19: Das Skript ändert den Hintergrund je nach Uhrzeit (uhrzeit.html).10
Abbildung 6.30: Dieser Screenshot ist von 13 Uhr mittags.
10 Dieses Skript funktioniert nicht im Netscape Navigator 4.x. Wie Sie mit CSS-Anweisungen auch für diesen Browser arbeiten, erfahren Sie in Kapitel 19 »CSS und JavaScript«.
KOMPENDIUM
JavaScript
193
Kapitel 6
Objekte
Abbildung 6.31: Die Sonne ist untergegangen. Ein Screenshot, aufgenommen um 22 Uhr
Dieselbe Idee können Sie natürlich auch verwenden, um beispielsweise täglich verschiedene Bilder einzusetzen oder im Wochenrhythmus Bilder zu wechseln. Uhrzeit aktualisieren Natürlich soll die Uhrzeit immer aktuell sein. Um dies zu realisieren, verwendet das folgende Beispielskript zwei neue Möglichkeiten von JavaScript. Die Funktion window.setInterval("Befehl", Millisekunden) ruft einen Befehl oder eine Funktion immer wieder auf, und zwar in regelmäßigen Abständen, die unter Millisekunden angegeben werden. var aufruf = window.setInterval("uhrzeit()", 500);
Das Gegenstück zu setInterval() ist clearInterval(ID). Diese Methode hebt ein Intervall wieder auf. Die ID ist der Variablenname, bei dem setInterval() aufgerufen wurde. Im vorhergehenden Beispiel heißt diese ID also aufruf. clearInterval(aufruf);
Die Ausgabe erfolgt nicht mit document.write(), sondern mit einem
-Block, der über getElementById() angesprochen wird, da nur so eine stets aktuelle HTML-Ausgabe in einer Seite möglich ist. 194
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
function uhrzeit() { var uhr = new Date(); document.getElementById("block").innerText = uhr.getHours() + ":" + uhr.getMinutes() + ":" + uhr.getSeconds();
} getElementById() ist eine Möglichkeit, über das DOM auf Elemente zurückzugreifen, funktioniert allerdings nicht in allen Browsern. Für den Netscape Navigator 4.x und den Internet Explorer 4 benötigen Sie andere Lösungen. Mehr dazu erfahren Sie in Kapitel 10 »Document Object Model«.
Nachfolgend der vollständige Code: Die Uhrzeit aktualisieren <script language="JavaScript">
Listing 6.20: Die Uhrzeit laufend aktualisieren (uhrzeit_aktualisieren.html)
var uhr = new Date(); document.getElementById("block").innerText = uhr.getHours() + ":" + uhr.getMinutes() + ":" + uhr.getSeconds();
} var aufruf = window.setInterval("uhrzeit()", 500);
//--> Abbildung 6.32: Stets die aktuelle Uhrzeit auf der Seite
Countdown Ähnlich wird auch ein Countdown realisiert. Hier wird nur innerhalb der Funktion das aktuelle Datum vom angestrebten Zieldatum abgezogen. Wenn Sie es wünschen, können Sie noch eine etwas kompliziertere Umrechnung hinzufügen, die den zurückgegebenen Betrag von Millisekunden in Tage, Stunden, Minuten und Sekunden umrechnet:
KOMPENDIUM
JavaScript
195
Kapitel 6 Listing 6.21: Ein Counter bis 1.1.2003 (counter.html)
Objekte Counter <script language="JavaScript">
} var aufruf = window.setInterval("counter()", 500); //--> Abbildung 6.33: Der Countdown zählt die Tage, Stunden, Minuten und Sekunden bis zum 1.1.2003 rückwärts.
Datum formatieren Die Daten in JavaScript werden – von den meisten Browsern – in englischer Form ausgegeben. Das heißt, nicht nur die Reihenfolge von Tag, Monat und Jahr ist ungewöhnlich, sondern auch die Monats- und Tagenamen passen nicht. Die Umformatierung des Datums ist allerdings nicht sehr aufwändig, wenn Sie die Methoden verwenden, um Elemente wie den Monat (getMonth()) einzeln auszugeben.
196
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Ein Beispiel zeigt dies. Ziel ist es, das Datum in normaler Form mit deutschem Monatsnamen auszugeben: 28. November 2002
Tag und Jahr sind kein Problem. Den Tag des Monats erhalten Sie mit getDate(), das vierstellige Jahr mit getFullYear().
Problematischer ist der Monat. getMonth() liefert den Monat als Zahl zwischen 0 (Januar) und 11 (Dezember). Für die Umwandlung gibt es zwei mögliche Wege: Eine switch- oder if-Fallunterscheidung, die alle Zahlen von 0 bis 11 durchprüft und entsprechend den Monatsnamen zurückliefert Ein Array mit den Monatsnamen Die zweite Lösung erscheint hier praktikabler, weil sie etwas einfacher und damit weniger fehleranfällig eingegeben werden kann. Das Beispiel verwendet Arrays, die in Kapitel 7 »Arrays und Strings« detaillierter besprochen werden. Das Array besteht aus den zwölf Monatsnamen. Die Indexnummern im Array entsprechen jeweils den Monatsnummern, die von getMonth() ausgegeben werden. Datum formatieren <script language="JavaScript">
Die Umformatierung von Daten ist auf manchen Websites eine sehr häufige Aufgabe. Hier lohnt es sich, die Umwandlung in eine Funktion oder eine Objektmethode zu packen und sie in einer externen JavaScript-Datei zur Verfügung zu stellen. Wir zeigen in Kapitel 8 »OOP«, wie Sie das DateObjekt um eine solche Methode erweitern können. Abbildung 6.34: Das Datum im manuell erstellten Format
Verbinden Sie die Datumsformatierung nun noch mit der Fallunterscheidung aus dem Abschnitt »Das Jahr-2000-Problem«, und Sie erhalten die Jahreszahl in korrekter Form auch für Netscape 2 und 3 und die erste Version des Internet Explorers 3. Listing 6.23: (Ausschnitt aus: datum_formatieren _y2k.html)
function getJahr2000(datum) { var jahr = datum.getYear(); if (jahr < 200) { return jahr + 1900; } else { return jahr; } } . . . var datum = new Date(); . document.write(getJahr2000(datum));
Neue und spezielle Methoden Einige Methoden für das Date-Objekt sind erst in neueren Browsern hinzugekommen oder beschränken sich speziell auf den Internet Explorer. Tabelle 6.7 gibt einen Überblick und Tabelle 6.8 zeigt, in welchen Browsern die Methoden funktionieren. 198
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6 Abbildung 6.35: Mit der Jahr-2000Fallunterscheidung funktioniert das Skript sogar im Netscape Navigator 2.
Methode
Beschreibung
toDateString()
wandelt ein Date-Objekt in einen String um. Enthält nur das Datum, nicht die Zeit. Ist auf den Internet Explorer beschränkt.
toLocaleString()
gibt das Datum und die Uhrzeit als String zurück, wie auf dem lokalen System vorgesehen. Das Ergebnis ist vom Browser abhängig.
toLocaleDateString()
gibt nur das Datum im lokalen Format, abhängig vom Browser, zurück.
toLocaleTimeString()
gibt nur die Zeit in einem lokalen Format zurück. Das Aussehen ist vom Browser abhängig.
getVarDate()
liefert das Datum in dem Format VT_DATE, das bei der Interaktion mit ActiveX- und DOM-Objekten benötigt wird. Es ist auf den Internet Explorer beschränkt.
toTimeString()
liefert nur die Zeit als String.
Tabelle 6.7: Die neueren und speziellen Methoden des DateObjekts
Auf der CD-ROM finden Sie im Ordner code\kap06 für jede Methode ein Beispiel. Der Dateiname entspricht jeweils dem Namen der Methode.
NS4.x NS6
NS7
toDateString() toLocaleString()
KOMPENDIUM
JavaScript
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 6.8: Neue Methoden von Date
199
Kapitel 6 Tabelle 6.8: Neue Methoden von Date (Forts.)
Objekte
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
toLocaleDateString()
toLocaleTimeString()
getVarDate() toTimeString
Prinzipiell ist insbesondere der Einsatz der lokalen Datums- und Zeitstrings durchaus sinnvoll. Der Internet Explorer liefert sogar deutsche Tages- und Monatsnamen (siehe Abbildung 6.36). Das ist allerdings in der Praxis kaum verwertbar, da der Navigator auch in der deutschen Version 7 englische Namen und ein etwas anderes Format einsetzt (siehe Abbildung 6.37). Solange hier keine Einigkeit herrscht, bleibt dem Entwickler nichts anderes übrig, als das Datum selbst zu formatieren. Abbildung 6.36: Der Internet Explorer 6 verwendet deutsche Tagesund Monatsnamen.
Abbildung 6.37: Der Navigator kann nur Englisch – und das auf dem selben Rechner.
200
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Vorgefertigte Datumsobjekte Das Browserobjekt document besitzt drei Methoden, die Datumsformate zurückliefern: lastModified() – Zeitpunkt, an dem das Dokument zuletzt gespeichert
wurde fileCreatedDate() – Zeitpunkt, an dem das Dokument erstellt wurde. Beschränkt auf den Internet Explorer fileModifiedDate() – ebenfalls der Zeitpunkt, an dem das Dokument
zuletzt bearbeitet wurde, allerdings auf den Internet Explorer beschränkt. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
fileCreatedDate()
fileModifiedDate()
lastModified()
Tabelle 6.9: Methoden mit vorgefertigten Datumsobjekten
Da die drei Methoden auf Informationen vom Server angewiesen sind, können die Ergebnisse sehr unpräzise sein. Diesen Funktionen sollten Sie daher nicht unbedingt trauen. Ein einfaches Beispiel gibt das Datum aus, an dem das aktuelle Dokument zuletzt geändert wurde. Dateiinfo <script language="JavaScript">
KOMPENDIUM
JavaScript
201
Kapitel 6
Objekte
Boolean Wahrheitswerte tauchen in der Programmierung an allen Ecken und Enden auf. Normalerweise müssen Sie sich darum nicht kümmern. Zusätzlich gibt es in JavaScript allerdings noch ein Boolean-Objekt. Dieses Objekt wird ebenfalls mit dem Konstruktor new instanziiert. Als Parameter übergeben Sie einen Wahrheitswert: var wahr = new Boolean(true);
Dieses Objekt besitzt zwei Methoden: toString() – liefert einen String, der entweder "true" oder "false" enthält. Wenn Sie einen Wahrheitswert ausgeben, erfolgt diese Umwandlung automatisch. valueOf() – gibt den Wert – also true oder false – des Boolean-Objekts
zurück. Das Boolean-Objekt und seine Methoden gibt es seit Netscape Navigator 3 und der zweiten Version des Internet Explorers 3, also seit JavaScript 1.1. Sie können das Boolean-Objekt wie alle JavaScript-eigenen Objekte um Ihre eigenen Methoden erweitern. Mehr dazu erfahren Sie in Kapitel 8 »OOP«.
Number Auch Zahlen werden, wie Wahrheitswerte, in JavaScript grundsätzlich einfach verwendet. Das Number-Objekt besitzt allerdings einige zusätzliche Eigenschaften und Methoden. Ein Number-Objekt wird wie folgt instanziiert: var zahl = new Number(25);
In Tabelle 6.10 sehen Sie die Eigenschaften des Number-Objekts. Tabelle 6.10: Die Eigenschaften des NumberObjekts
202
Eigenschaft
Beschreibung
MAX_VALUE
Die größte mögliche Zahl in JavaScript
MIN_VALUE
Die kleinste mögliche Zahl in JavaScript
NaN
Alle Objekte, die keine Zahl sind. Dies geschieht vor allem beim Rechnen mit Strings oder bei der Umwandlung von Strings in Zahlen. Sie testen mit der globalen Funktion isNaN(), ob es sich um den Datentyp NaN handelt (siehe Kapitel 5 »Funktionen«).
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6 Tabelle 6.10: Die Eigenschaften des NumberObjekts (Forts.)
Eigenschaft
Beschreibung
POSITIVE_INFINITY
Positive Unendlichkeit (; alle Zahlen, die größer als die größte mögliche Zahl in JavaScript sind
NEGATIVE_INFINITY
Negative Unendlichkeit (- ); alle Zahlen, die kleiner als die kleinste mögliche Zahl in JavaScript sind
Das Number-Objekt ist in JavaScript bereits eine lange Zeit enthalten. Nur Netscape 2 und der Internet Explorer 3 in Version 1 bleiben außen vor. Die Eigenschaften sind ebenfalls seit dieser Zeit integriert. Die Methoden sind teilweise neuer. Die folgende Tabelle gibt Ihnen eine Übersicht: NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
toExponential()
toFixed()
toLocaleString()
toPrecission()
K3
Tabelle 6.11: Die Methoden des Number-Objekts
toString()
valueOf()
Methode
Beschreibung
toExponential(Stellen)
wandelt das Number-Objekt in Exponentialschreibweisea um und gibt es als String zurück. Als Parameter können Sie die Zahl der Dezimalstellen angeben.
toFixed(Stellen)
wandelt eine Zahl in die Dezimalzahlschreibweise um. Die Zahl der Nachkommastellen wird dabei exakt festgelegt. Falls nötig, rundet der Interpreter. Dafür wird nur die Stelle als Referenz genommen, die genau hinter der erlaubten Stellenzahl liegt. Bei 44.3248 und einer Stellenzahl von 2 also die 4. Die Rückgabe erfolgt als String.
toLocaleString()
konvertiert die Zahl in das Standardformat auf dem lokalen System. Dies ist von Browser zu Browser unterschiedlich. Die Rückgabe erfolgt als String.
Tabelle 6.12: Die Methoden des Number-Objekts
77.777 wird im Internet Explorer 6 beispielsweise als 77.78 ausgegeben, im Netscape Navigator 7 dagegen als 77.777.
KOMPENDIUM
JavaScript
203
Kapitel 6 Tabelle 6.12: Die Methoden des Number-Objekts (Forts.)
Objekte
Methode
Beschreibung
toPrecision(Stellen)
gibt eine Zahl mit der exakten Stellenzahl an, und zwar auch vor dem Dezimalpunkt. 34.678 wird bei einer Präzision von 2 Stellen zu 35. Eine Präzision von 4 Stellen ergibt 34.68.
Auch bei dieser Funktion wird die Stelle nach der angestrebten Stellenzahl zum Runden verwendet. Stellen danach werden entfernt. Die Rückgabe erfolgt als String. toString()
wandelt eine Zahl in einen String um.
valueOf()
liefert den Wert eines Number-Objekts.
a.
zur Exponentialschreibweise siehe Kapitel 3 »Syntax und Variablen«
Ein einfaches Beispiel steht hier stellvertretend für die übrigen Methoden des Number-Objekts. Der Code gibt mit der Methode toExponential() die Zahl 700 in Exponentialschreibweise aus: Listing 6.25: toExponential()
(toexponential.html)
toExponential <script language="JavaScript">
//--> Abbildung 6.38: 700 in Exponentialschreibweise
Browser-spezifische Objekte Neben den allgemein verfügbaren Objekten gibt es auch Browser-spezifische Objekte. Sie sind allerdings nicht mit den Browserobjekten zu verwechseln, die Zugriff auf das Browserfenster und seinen Inhalt bieten. 204
KOMPENDIUM
JavaScript
Objekte von JavaScript
Kapitel 6
Die Browser-spezifischen Objekte bieten spezielle Funktionalitäten, die meist nur einer der großen Browser besitzt. Windows-Objekte Der Internet Explorer unter Windows unterstützt einige Objekte, die JavaScript die Arbeit mit dem Betriebssystem erlauben soll. Der Kontakt funktioniert hier hauptsächlich über so genannte ActiveX-Objekte. Hier handelt es sich wirklich nur um den Internet Explorer für Windows und nicht um den Mac. Da diese Objekte auf den Internet Explorer und noch enger auf Windows beschränkt sind und weniger JavaScript- (bzw. JScript-), sondern eher ActiveX-Programmierung erfordern, finden Sie in diesem Buch nur eine kurze Beschreibung. Folgende Objekte stehen zur Verfügung: ActiveXObject – dient zum Zugriff und zur Verwaltung der Internet
Explorer-ActiveX-Objekte Dictionary – speichert Werte mit ihrem Schlüssel. Da JavaScript assoziative Arrays unterstützt, die dasselbe können, ist dieses Objekt eigentlich überflüssig und wurde wohl hauptsächlich für VBScript-Programmierer eingeführt. Enumeration – erlaubt den Zugriff auf Kollektionen aus verschiedenen
Eigenschaften. Diese Eigenschaften können beispielsweise die Eigenschaften eines Browserobjekts sein. Da es in JavaScript allerdings den Direktzugriff über das DOM gibt, ist auch dieses Objekt in der Praxis kaum in Gebrauch. FileSystemObject – erlaubt den Zugriff auf das Dateisystem. Dateien
können geschrieben, geöffnet und gespeichert werden. Allerdings ist dies abhängig von den Sicherheitseinstellungen des Internet Explorers. Der Gedanke liegt nahe, diese praktische Funktionalität in einem Intranet zu verwenden, das auf Windows-Maschinen mit IE basiert. Das Problem besteht jedoch darin, dass die Sicherheitseinstellungen im IE recht lax sein müssen, damit der Zugriff auf das Dateisystem erlaubt ist. Da die Rechner im Intranet aber meistens auch am Internet hängen, damit die Mitarbeiter dort surfen können, erscheint dies vielen Administratoren als nicht empfehlenswert. VBArray – gestattet den Zugriff auf Visual Basic-Arrays, die nur gelesen werden können. Diese Arrays sind meist Rückgabewerte eines ActiveXObjekts.
KOMPENDIUM
JavaScript
205
Kapitel 6
Objekte Global Das Objekt Global ist ein merkwürdiger Geselle. Es ist eine Art Überobjekt. Alle Variablen und Funktionen, die Sie deklarieren, sind Teil des GlobalObjekts. Da es aber selbst nicht in Erscheinung tritt, brauchen Sie sich nicht darum zu kümmern. Wichtig ist nur, dass aufgrund dieses Objekts Variablen und Funktionen im gesamten Skript zur Verfügung stehen. Error Das Error-Objekt ist noch recht neu. Es dient zur Fehlerkontrolle. Sie können damit beispielsweise eigene Ausnahmen als Fehler definieren und entsprechend darauf reagieren.
Tabelle 6.13: Das Error-Objekt
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Mehr zum Fehlerhandling erfahren Sie in Kapitel 9 »Debugging«.
206
KOMPENDIUM
JavaScript
7
Arrays und Strings
Dieses Kapitel ist zwei der wichtigsten Datentypen gewidmet: Arrays und Strings. Arrays sind Sammlungen von Daten und daher bereits ein »fortgeschrittenes« Programmierkonstrukt. Aber was machen die bereits zur Genüge bekannten Strings hier? »Zur Genüge bekannt« stimmt nur halb. In diesem Kapitel finden Sie das String-Objekt und erfahren, wie Sie Teile eines Strings ausschneiden, eine Zeichenkette in Strings suchen und String-Formatierungen ändern.
7.1
Arrays
Ein Array speichert beliebig viele Daten.1 Diese Daten werden im Array nacheinander angeordnet. Sie können sich dies wie eine Perlenschnur vorstellen. Damit Daten auch wieder auffindbar sind, werden sie mit einem Index versehen. Der Index eines Arrays beginnt bei 0. Das erste Element hat also den Index 0, das zweite den Index 1 usw. Ein Array ist in JavaScript ein Objekt, daher wird es mit dem Konstruktor new instanziiert. var Arrayname = new Array();
Das Array-Objekt steht in JavaScript schon immer zur Verfügung. Nur im Netscape 2 und im Internet Explorer 3 in der ersten Version wird ein Array nicht als Objekt angesehen. Daher sind die Eigenschaften und Methoden nicht vorhanden. Erstellen und auslesen können Sie ein Array allerdings auch dort.
1
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 7.1: Das Array-Objekt
Ab einer gewissen Datenmenge leidet beim Eingeben und Auslesen die Performance. Dies ist allerdings in der Praxis kaum relevant.
KOMPENDIUM
JavaScript
207
Kapitel 7
Arrays und Strings Neue Elemente fügen Sie mit dem Array-Namen und dem Index hinzu: Arrayname[0] = Wert;
Diese Zeile weist also dem ersten Array-Element einen Wert zu. Der Index steht immer in eckigen Klammern hinter dem Array-Namen. Der Internet Explorer kommt auch mit einem Index in runden Klammern zurecht. Da hier aber bereits der Netscape Navigator scheitert, sollten Sie immer eckige Klammern verwenden. Dies gilt auch für ein Intranet, das vollständig mit Internet Explorern ausgestattet ist, denn wer weiß schon, wo das Skript überall eingesetzt werden muss und was auf hunderten oder tausenden von Rechnern installiert ist. Das folgende kleine Beispiel erzeugt ein Array und füllt danach die ersten drei Array-Elemente mit Strings: var namen = new Array(); namen[0] = "Carolin"; namen[1] = "Christine"; namen[2] = "Phillip";
Wenn Sie die Daten erst einmal im Array gespeichert haben, benötigen Sie natürlich Zugriff darauf. Eines der Elemente im Array sprechen Sie wie folgt an: Arrayname[Index]
Soll also aus dem Beispiel-Array der Name »Christine« ausgegeben werden, ist die folgende Zeile ausreichend: document.write(namen[1]); Abbildung 7.1: Der Browser zeigt das richtige Element aus dem Array.
208
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
Alternativen und Kurzformen Die soeben gezeigte Möglichkeit, ein Array zu definieren und zu füllen, ist nicht die einzige. Als Parameter für das Array-Objekt können Sie auch gleich zu Beginn die Länge des Arrays angeben: var Arrayname = new Array(Laenge);
Wenn Sie ein Array ohne Länge erzeugen, hat es keine Elemente. Geben Sie dagegen am Anfang eine Länge an, wird gleich die entsprechende Anzahl an Elementen reserviert. Jedes der Elemente erhält den Wert undefined. Die Eigenschaft length (siehe Abschnitt »Elemente ändern«) des Array-Attributs erhält in diesem Fall den Wert, den Sie im Array-Objekt als Parameter angegeben haben. Die Angabe der Länge als einziger Parameter funktioniert in sehr alten Browsern, namentlich Netscape 2 und Internet Explorer 3 in der ersten Version nicht. Statt der Länge können Sie als Parameter für das Array-Objekt auch gleich die Array-Elemente eintragen: var Arrayname = new Array(Element1, Element2, ...);
In dieser Variante werden die Indexnummern automatisch zugewiesen. Element1 hat also Index 0, Element2 Index 1 usw. Die dritte Kurzform kommt ganz ohne new-Konstruktor und Array-Objekt aus, steht dafür aber in eckigen Klammern: var Arrayname = [Element1, Element2, Element3, ...];
Diese Variante heißt auch Array-Literal, da der Variablen direkt ein Literal mit dem Array zugewiesen wird. Das Array-Literal steht im Gegensatz zum Array-Objekt im Netscape Navigator 3 noch nicht zur Verfügung. Sie benötigen Browser ab Internet Explorer 4 und Netscape Navigator 4.x. Datentypen mischen In einem Array können Sie die Datentypen beliebig mischen. var mischen = new Array(1, "text", true);
KOMPENDIUM
JavaScript
209
Kapitel 7
Arrays und Strings Andere Programmiersprachen wie beispielsweise Java erlauben dies in dieser Form nicht. Da JavaScript aber nur schwach typisiert, also beispielsweise eine automatische Typänderung möglich ist, gibt es bei Datentypen in Arrays keine Beschränkungen. Arrays verschachteln Wenn beliebige Datentypen in einem Array speicherbar sind, warum dann nicht auch mehrere Arrays2? Folgender Code erstellt ein Array und weist es dann einem neuen Array als einzelnes Element zu: var namen = new Array(); namen[0] = "Carolin"; namen[1] = "Christine"; namen[2] = "Phillip"; var alle = new Array(namen, "Katrin");
Eine alternative Definitionsmethode von verschachtelten Arrays erfolgt mit eckigen Klammern: var alle = [["Carolin", "Christine", "Phillip"], "Katrin"];
Der Zugriff auf das Element erfolgt wie gewöhnlich. Geben Sie es beispielsweise direkt aus: document.write(alle[0]);
Mit dieser Zeile geben Sie das komplette erste Array aus (siehe Abbildung 7.2). Abbildung 7.2: Das Array liefert alle drei Elemente.
Dies ist häufig nicht der gewünschte Effekt. Daher dürfen Sie ein Element im verschachtelten Array auch direkt ansprechen. Dazu folgt der Indexwert des zweiten Arrays in eckigen Klammern nach dem ersten: document.write(alle[0][1]);
2
210
Verschachtelte Arrays heißen auch mehrdimensionale Arrays.
KOMPENDIUM
JavaScript
Arrays
Kapitel 7 Abbildung 7.3: Der doppelte Index gibt nur noch einen Namen zurück.
Wie tief Sie ein Array verschachteln, bleibt Ihnen überlassen. Auch eine dreifache Verschachtelung ist möglich, wie das folgende Beispiel zeigt. Allerdings wird es hier bereits sehr unübersichtlich. Arrays verschachteln <script language="JavaScript">
Listing 7.1: Drei Arrays ineinander verschachteln (array_verschachteln_ drei.html)
Die Ausgabe bleibt das zweite Element aus dem Array namen (siehe Abbildung 7.4). Abbildung 7.4: Der zweite Eintrag aus dem ersten Array
Was hier mit Strings eher eine Lernübung ist, kann bei der Programmierung durchaus praktisch sein. Denken Sie nur an Zahlenmatrizen, die Sie mit mehrdimensionalen Arrays miteinander verknüpfen können.
KOMPENDIUM
JavaScript
211
Kapitel 7
Arrays und Strings
Elemente ändern Um Elemente in einem Array zu ändern, ist es ausreichend, dem Index einen anderen Wert zuzuweisen. Folgender Code ändert das dritte Element des Arrays von »Phillip« in »Steffi«: var namen = new Array("Carolin", "Christine", "Phillip"); namen[2] = "Steffi";
Bei Änderungen darf selbstverständlich auch der Datentyp wechseln.
Die Länge eines Arrays Die length-Eigenschaft enthält die Länge eines Arrays, also die Zahl der Elemente. Die Abfrage erfolgt sehr einfach in Punktnotation: var namen = new Array("Carolin","Christine","Phillip"); document.write(namen.length); Abbildung 7.5: Das Array besteht aus drei Elementen.
Zur Berechnung der Länge des Arrays verwendet die Eigenschaft length intern das letzte Array-Element und addiert 1. Sind dazwischen Array-Elemente leer geblieben, wird dies nicht berücksichtigt. Listing 7.2: Probleme mit der length-Eigenschaft (array_laenge_ problem.html)
Probleme mit length <script language="JavaScript">
//-->
Dieses Listing gibt 4 als Länge aus, obwohl der Index 1 kein Element besitzt.
212
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
for-in- und andere Schleifen Der for-in-Schleife wurde bisher in Kapitel 4 »Programmieren« nur wenig Platz eingeräumt. Das liegt nicht daran, dass sie so unwichtig wäre, sondern an ihrem speziellen Anwendungsgebiet. Die for-in-Schleife dient hauptsächlich dazu, Elemente aus Arrays und Eigenschaften von Objekten auszulesen. Die Syntax zeigt die Schlüsselrolle des Operators in: for (Variable in Array) { Anweisungen; }
Die Schleife wird so lange durchlaufen, wie sich Elemente im Array befinden. Bei jedem Schleifendurchlauf wird der Index des aktuellen Elements in der Variablen gespeichert. Wie nützlich dies ist, zeigt das folgende Beispiel: var namen = new Array("Carolin","Christine","Phillip"); for(var i in namen) { document.write("Index " + i + ": "); document.write(namen[i] + " "); }
Listing 7.3: Ein Array mit for-in auslesen (array_forin.html)
Hier prüft die for-in-Schleife das Array namen. Solange Elemente darin enthalten sind, wird der Variablen i der Index des soeben durchlaufenen Objekts übergeben. In den Schleifenanweisungen greift die Ausgabe mit dem Index auf die Array-Elemente zu. Abbildung 7.6: Der Index und die Array-Elemente erscheinen im Browser.
Andere Schleifen Als Alternative zur for-in-Schleife verwenden Sie einfach eine andere Schleifenart und überprüfen in der Bedingung die Länge des Arrays. Achten Sie aber darauf, dass die Länge immer um 1 höher ist als der Index.
KOMPENDIUM
JavaScript
213
Kapitel 7
Arrays und Strings Das folgende Beispiel verwendet eine gewöhnliche for-Schleife:
Listing 7.4: Ein Array mit for auslesen (array_for.html)
Array mit for <script language="JavaScript">"); }
//-->
Das Beispiel erzeugt dieselbe Ausgabe, wie in Abbildung 7.6 zu sehen. Achten Sie darauf, dass die Ausgabe mit der Prüfung von length auch die undefinierten Elemente mitliefert, wenn in einem Array nicht alle Elemente definiert sind. Listing 7.5: Die for-Ausgabe mit dem bekannten length-Problem (for_length_ problem.html)
var namen = new Array(); namen[0] = "Carolin"; namen[2] = "Christine"; namen[3] = "Phillip"; for(var i = 0; i < namen.length; i++ ) { document.write("Index " + i + ": "); document.write(namen[i] + " "); }
Der Code aus Listing 7.5 liefert also für Index 1 den Wert undefined. Abbildung 7.7: Index 1 ist undefined.
214
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
Eine for-in-Schleife vermeidet dies, da sie undefinierte Werte ignoriert: for(var i in namen) { document.write("Index " + i + ": "); document.write(namen[i] + " "); }
Listing 7.6: Die for-in-Schleife gibt nur definierte Elemente aus (forin_problem. html) Abbildung 7.8: Der Index 1 wird nicht ausgegeben.
Array-Elemente löschen Um ein Array-Element zu löschen, ist es ausreichend, ihm einen leeren String oder den Datentyp null zuzuweisen. Dabei gibt es aber ein Problem: Das Element wird auch in einer for-in-Schleife ausgegeben. Es ist also noch als Array-Element vorhanden. Ab Netscape Navigator 4 und Internet Explorer 4 bietet JavaScript allerdings eine Alternative. Sie können mit dem Schlüsselwort delete einzelne Array-Elemente löschen. Das folgende Beispiel illustriert dies. Zuerst wird das Element mit Index 0 gelöscht, anschließend werden in einer for-in-Schleife alle übrig gebliebenen Elemente ausgegeben: Mit delete Array-Elemente löschen <script language="JavaScript">
Listing 7.7: Mit delete ArrayElemente entfernen (delete.html)
delete namen[0]; for(var i in namen) { document.write("Index " + i + ": "); document.write(namen[i] + " "); }
//-->
KOMPENDIUM
JavaScript
215
Kapitel 7
Arrays und Strings
Abbildung 7.9: Der Eintrag bei Index 0 wurde entfernt.
Assoziative Arrays Ein assoziatives Array ist ein Array, das statt eines numerischen Index einen Index mit Namen besitzt. Der Name hat den Datentyp String und muss daher in Anführungszeichen stehen. Listing 7.8: Ein assoziatives Array (assoziativ.html)
var namen = new Array(); namen["Carolin"] = 13; namen["Christine"] = 10; namen["Phillip"] = 8;
Die Elemente in einem assoziativen Array werden immer mit ihrem Indexnamen angesprochen, also beispielsweise namen["Phillip"]
Natürlich können Sie auch mit einer for-in-Schleife auf das assoziative Array zugreifen. Die Syntax gleicht der bei einem gewöhnlichen Array: for(var i in namen) { document.write("Index " + i + ": "); document.write(namen[i] + " "); } Abbildung 7.10: Der Index ist eine Zeichenkette; damit werden die Elemente ausgegeben.
216
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
In der Praxis dienen assoziative Arrays hauptsächlich dazu, Schlüssel/ Daten-Paare zu speichern. Länge Assoziative Arrays haben eine Schwäche: Die length-Eigenschaft berücksichtigt assoziative Elemente nicht. Daher können Sie assoziative Elemente nur mit der for-in-Schleife auslesen und nicht, wie bei gewöhnlichen Arrays (siehe Listing 7.4), mit einer anderen Schleife. Folgendes Beispiel zeigt dies. Die Ausgabe der Länge ergibt nur den Wert 1, da die drei assoziativen Array-Elemente ignoriert werden. Assoziatives Array <script language="JavaScript">
Listing 7.9: Assoziative Elemente zählen nicht zur Länge des Arrays. (assoziativ_length. html)
//--> Abbildung 7.11: Das Array hat nur eine Länge von 1.
Methoden für Arrays Das Array-Objekt bietet einige Methoden, um mit Arrays zu arbeiten. Darunter befinden sich Methoden, um Arrays zu sortieren, zu verbinden oder die Reihenfolge umzudrehen. Da die Methoden in der Praxis bedeutsam sind, finden Sie sie in den nächsten Abschnitten jeweils mit Beispiel erklärt.
KOMPENDIUM
JavaScript
217
Kapitel 7
Arrays und Strings Sortieren mit sort() Die Funktion sort() dient dazu, die Elemente eines Arrays zu sortieren. Die Funktion steht ab Netscape 3 und Internet Explorer 3 in der zweiten Version zur Verfügung.
Tabelle 7.2: sort()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Die Sortierung erfolgt standardmäßig alphabetisch. Allerdings werden zum Vergleich die ASCI-Codes der einzelnen Zeichen herangezogen. Das bedeutet, dass Kleinbuchstaben immer größer als Großbuchstaben sind. Dieses Problem kennen Sie bereits von den Vergleichsoperatoren in Kapitel 4.1 im Abschnitt »Vergleich von Strings«. Bei Zahlenwerten erfolgt die Sortierung mit sort() ebenfalls über die ASCIIWerte. Zahlen werden also in Strings umgewandelt. Bei diesem System ist 9 größer als 15, da immer zuerst das erste Zeichen verglichen wird. Ist das erste Zeichen also schon unterschiedlich, steht die Sortierreihenfolge fest. In der Praxis ist die Sortierung von Zahlenwerten mit sort() daher nicht verwendbar. Alternativ können Sie für die sort()-Methode eine Sortierfunktion definieren. Ein Wahrheitswert true oder false erfährt für die Sortierung ebenfalls eine Umwandlung in einen String. Anschließend wird also der String »true« oder »false« mit den anderen Array-Elementen als Strings verglichen. Auch dies hat in der Praxis meist keinen Wert. Einsetzbar ist die Methode sort() alleine also am besten für Strings, die beispielsweise einheitlich mit Groß- oder Kleinschreibung beginnen. Der folgende Beispiel-Code sortiert ein Array mit drei Namen in die alphabetische Reihenfolge: Listing 7.10: Mit sort() arbeiten (sort.html)
Sort() <script language="JavaScript">
for(var i in namen) { document.write("Index " + i + ": "); 218
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
document.write(namen[i] + " "); } //--> Abbildung 7.12: Die Array-Elemente haben die Reihenfolge und damit auch den Index getauscht.
Ein assoziatives Array können Sie nicht sortieren, da die Elemente keine festgelegte Reihenfolge haben (auf der CD-ROM zu finden unter code\kap07\sort_assoziativ.html) Sortieren mit Funktion sort() kann als optionalen Parameter eine Funktion übernehmen: sort(Funktion)
Die Funktion enthält Anweisungen für die Sortierung. Wie funktioniert das? sort() schickt nacheinander jedes mögliche Paar aus zwei Array-Elementen an diese Funktion. Die Funktion muss diese zwei Elemente miteinander vergleichen. Wenn das erste Element größer als das zweite ist, gibt die Funktion einen negativen Wert zurück, ist es kleiner, einen positiven. Aus diesem Wert erkennt sort() also, welches der beiden Elemente größer ist. Hat die Methode alle Werte für alle möglichen Zweierpaarungen von Elementen, kann daraus auf die Rangfolge geschlossen werden. Ein Beispiel zeigt dies. Das Array besteht aus drei Zahlenwerten: var zahlen = new Array(); zahlen[0] = 15; zahlen[1] = 42; zahlen[2] = 9;
Die Sortierung erfolgt mit sort(). Als Parameter wird die Funktion sort_funk aufgerufen, die die Sortieranweisungen enthält.
KOMPENDIUM
JavaScript
219
Kapitel 7
Arrays und Strings zahlen.sort(sort_funk);
Die Sortierfunktion übernimmt die zwei Parameter. Sie erinnern sich? Die sort()-Methode übergibt zwei der Array-Elemente immer als zwei Parameter. Diese Parameter werden voneinander subtrahiert und das Ergebnis ist der Rückgabewert. Er ist negativ, wenn y größer als x ist und positiv, wenn x größer als y ist. function sort_funk(x,y) { return x - y; }
Zuletzt gibt eine for-in-Schleife die Array-Elemente aus, um zu testen, wie sich die Sortierung ausgewirkt hat. for(var i in zahlen) { document.write("Index " + i + ": "); document.write(zahlen[i] + " "); }
Nachfolgend das vollständige Beispiel: Listing 7.11: Eine Sortierfunktion einsetzen (zahlen.html)
Sort() mit Funktion <script language="JavaScript">"); }
//-->
Ein verbreiteter Irrtum ist, dass der Rückgabewert der Funktion +1 oder -1 sein müsste. Ein positiver oder negativer Wert ist ausreichend, wie das vorangegangene Beispiel zeigt. Häufig wird nur +1 oder -1 als vorgegebener Rückgabewert verwendet.
220
KOMPENDIUM
JavaScript
Arrays
Kapitel 7 Abbildung 7.13: Die Zahlen sind numerisch sortiert.
concat() Die Methode concat() verbindet zwei Arrays miteinander. Die Methode ist in der dritten Generation der Netscape- und Microsoft-Browser noch nicht integriert, in späteren Browsern aber verfügbar. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 7.3: concat()
Die Syntax von concat() ist einfach: var Array_gesamt = Array1.concat(Array2);
Dabei wird Array2 an Array1 angehängt. Natürlich kann Array_gesamt auch Array1 oder Array2 sein. In einem der beiden Arrays können also die Elemente beider zusammengefasst werden. Array1 = Array1.concat(Array2);
Das folgende Beispiel macht aus zwei Arrays mit Namen ein Array, das alle Namen enthält. concat() <script language="JavaScript">
Listing 7.12: Der Einsatz von concat()
(concat.html)
var gesamt = namen.concat(namen2);
for(var i in gesamt) { document.write("Index " + i + ": "); document.write(gesamt[i] + " "); } //-->
KOMPENDIUM
JavaScript
221
Kapitel 7
Arrays und Strings
Abbildung 7.14: Die zwei Arrays sind miteinander in einem verbunden.
Natürlich können auch assoziative Arrays und Arrays mit assoziativen Elementen zusammengelegt werden. join() join("Trennzeichen") gibt alle Elemente eines Arrays hintereinander als String
zurück. Als Trennzeichen können Sie einen beliebigen String angeben. join() ist in den gängigen Browsern vorhanden, nur Netscape 2 und Internet
Explorer 3 in der ersten Version (JavaScript 1.0) unterstützen es nicht, da sie auch das Array-Objekt nicht unterstützen. Tabelle 7.4: join()
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel zeigt, dass sogar der Einsatz von HTML-Tags möglich ist: Listing 7.13: join() (join.html)
join() <script language="JavaScript">");
document.write(text); //-->
222
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
Abbildung 7.15: Die Elemente des Arrays mit Strichpunkten und Zeilenumbruch getrennt
Das Ausgangs-Array wird von der Methode join() nicht geändert. Wird der Rückgabewert von join() einer Variablen zugewiesen, hat diese Variable den Datentyp String und keine Verbindung mehr zum Original-Array. reverse() Die Methode reverse() dreht die Reihenfolge der Elemente in einem Array um.3 reverse() ist wie join() in den gängigen Browsern vorhanden. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 7.5: reverse()
Das folgende Skript sortiert die Namen aus dem Array in umgekehrter Reihenfolge: reverse() <script language="JavaScript">
Listing 7.14: reverse() im Einsatz (reverse.html)
namen = namen.reverse();
for(var i in namen) { document.write("Index " + i + ": "); 3
In einem assoziativen Array macht diese Methode keinen Sinn, da assoziative Indexnamen keine Reihenfolge vorgeben.
KOMPENDIUM
JavaScript
223
Kapitel 7
Arrays und Strings document.write(namen[i] + " "); } //-->
Abbildung 7.16: Die Elemente im Array haben ihre Plätze getauscht.
slice() Die Methode slice() schneidet Elemente aus einem Array heraus und bildet daraus ein neues Array. Dabei wird als erster, verpflichtender Parameter das Startelement angegeben, ab dem ausgeschnitten wird. var Array_neu = Array.slice(2);
Die vorhergehende Zeile liefert ein neues Array, das alle Elemente des alten Arrays ab Indexnummer 2 besitzt. Als zweiten optionalen Parameter können Sie ein Element angeben, bei dem das Ausschneiden endet. Dieses Element wird nicht mehr ausgeschnitten. var Array_neu = Array.slice(2,3);
Diese Code-Zeile schneidet also nur das Element 2 aus dem alten Array aus und weist es dem neuen Array zu. slice() ist nicht in der dritten Generation des Internet Explorers und Net-
scape Navigators enthalten, dafür aber in allen neueren Versionen, wie der folgenden Tabelle zu entnehmen ist: Tabelle 7.6: slice()
224
NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
Das folgende Beispiel schneidet zwei Elemente aus einem Array aus und übergibt sie an ein neues Array (mit Namen neu), das anschließend ausgegeben wird: slice() <script language="JavaScript">
Listing 7.15: Die Methode slice()
(slice.html)
var neu = namen.slice(1,3);
for(var i in neu) { document.write("Index " + i + ": "); document.write(neu[i] + " "); } //--> Abbildung 7.17: Zwei Elemente aus dem alten Array wurden in das neue Array übernommen.
Mit assoziativen Arrays funktioniert die Methode slice() nicht, da hier Start- und Endposition nicht als Indexwert definierbar sind. Negative Werte für den zweiten Parameter wie bei String.slice() sind ebenfalls nicht möglich. slice() mit einer Funktion einfügen Das slice() nicht mit dem Netscape Navigator 3 funktioniert, ist meist unproblematisch. Wünschen Sie dagegen die größtmögliche Abwärtskompatibilität, können Sie slice() auch durch eine Funktion ersetzen, die dieselben Aufgaben bewerkstelligt:
KOMPENDIUM
JavaScript
225
Kapitel 7 Listing 7.16: Statt slice() eine selbst geschriebene Funktion verwenden (slice_funktion. html)
Arrays und Strings <script language="JavaScript">
var namen = new Array(); namen[0] = "Carolin"; namen[1] = "Christine"; namen[2] = "Phillip"; namen[3] = "Konstantin"; var neu = array_neu(namen, 1, 3);
for(var i in neu) { document.write("Index " + i + ": "); document.write(neu[i] + " "); } //--> Abbildung 7.18: Mit einer Funktion lassen sich Elemente aus einem Array auch im Netscape 3 auslesen.
splice() Die splice()-Methode ist recht mächtig. Sie entfernt Elemente aus der Mitte eines Arrays und kann sie einem neuen Array zuweisen.
226
KOMPENDIUM
JavaScript
Arrays
Kapitel 7
splice() ist im Internet Explorer erst seit Version 5.5 enthalten. Der Navigator hat diese Methode seit Version 4.x. NS4.x NS6
NS7
IE4 IE5
IE5.5 IE6
O7
M1
K3
Tabelle 7.7: splice()
Im Folgenden sehen Sie die Syntax: var Array_neu = Array.splice(Start, Elementzahl, Ersatz1, Ersatz2, ); splice() löscht ab dem bei Start angegebenen Index so viele Elemente, wie die Elementzahl vorgibt. Diese beiden Parameter sind verpflichtend, die wei-
teren Parameter nur optional. Sie erhalten jeweils einen Datensatz als Ersatz für die herausgelöschten Daten. Sind weniger Ersatzdaten als gelöschte Daten vorhanden, werden die Daten ab Start ersetzt und die letzten nur gelöscht. Wenn Sie mehr Daten einsetzen als herauslöschen, werden diese Daten hinzugefügt. Schalten Sie die zu löschende Elementzahl auf 0, fügt der JavaScript-Interpreter sogar nur Daten ein. Das folgende Beispiel löscht nur den Index Nummer 1, da als Elementzahl nur 1 angegeben ist: splice() <script language="JavaScript">
Listing 7.17: splice() in Aktion (splice.html)
var neu = namen.splice(1,1);
for(var i in neu) { document.write("Index " document.write(neu[i] + } for(var j in namen) { document.write("Index " document.write(namen[j] } //-->
KOMPENDIUM
JavaScript
+ i + ": "); " ");
+ j + ": "); + " ");
227
Kapitel 7
Arrays und Strings
Abbildung 7.19: Das neue Array hat als Index 0 das Element aus dem alten Array. Im alten Array fehlt das Element.
push() und pop() push(Wert) fügt einen Wert am Ende des Arrays hinzu, pop() entfernt das
letzte Element des Arrays. Dabei müssen Sie nicht wissen, welche Indexposition das letzte Element besitzt. push() und pop() sind im Internet Explorer erst seit Version 5.5 enthalten. Der Navigator besitzt sie seit Version 4.x. Tabelle 7.8:
NS4.x NS6
NS7
push()
pop()
push() und pop()
IE4 IE5
IE5.5 IE6
O7
M1
K3
Das folgende Beispiel zeigt push() und pop() im Einsatz: Ein HTML-Formular besteht aus einem großen Textbereich (