JavaScript  –  Das Handbuch für die Praxis - David Flanagan - E-Book

JavaScript – Das Handbuch für die Praxis E-Book

David Flanagan

0,0

Beschreibung

Seit 25 Jahren das begleitende Grundlagenwerk zu JavaScript - Durchgehend überarbeiteter Bestseller in der 7. Auflage - Deckt die Version ES2020 inkl. Tools/Extensions & Node.js ab - Vermittelt umfassendes und tiefgehendes JavaScript-Know-how JavaScript ist die Programmiersprache des Webs und der Bestseller "JavaScript: Das Handbuch für die Praxis" seit fast 25 Jahren und über sieben Auflagen ein geschätztes Grundlagenwerk für diese Sprache. Umfassend und detailliert dokumentiert Flanagan die wichtigsten client- und serverseitigen APIs. Die 7. Auflage wurde vollständig aktualisiert und deckt die Version 2020 von JavaScript ab. Freuen Sie sich auf spannende und inspirierende Codebeispiele und neue Kapitel über Klassen, Module, Iteratoren, Generatoren, Promises und async/await. Das Buch wendet sich an JavaScript-Neulinge mit Programmierkenntnissen sowie JavaScript-Programmierende, die ihr Verständnis vertiefen wollen. Die Zeit, die Sie in die Lektüre investieren, wird sich durch eine deutlich gesteigerte Produktivität garantiert rasch auszahlen.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 1231

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0



Lob für JavaScript: Das Handbuch für die Praxis, siebte Auflage

»In diesem Buch erfahren Sie Dinge über JavaScript, von denen Sie bisher nicht einmal geahnt hatten, wie dringend Sie sie wissen wollten. Die Qualität Ihres Codes und Ihre Produktivität werden extrem davon profitieren. Davids Wissen über JavaScript, dessen Feinheiten und typische Fehlerquellen ist verblüffend, und seine Qualitäten sind in diesem wirklich außergewöhnlichen Handbuch überall spürbar.«

– Schalk Neethling, Senior Frontend Engineer bei MDN Web Docs

»David Flanagan nimmt die Leser mit auf eine Führung durch die JavaScript-Welt und vermittelt Ihnen ein komplettes Bild aller Sprachfeatures und des gesamten Ökosystems.«

– Sarah Wachs, Frontend Developer und Women Who Code Berlin Lead

»Für alle Entwicklerinnen und Entwickler, die produktiv an Codebasen aus unterschiedlichsten Entwicklungsstadien von JavaScript arbeiten wollen (einschließlich der neuesten Funktionen), wird es sich auszahlen, sich intensiv auf dieses umfassende und maßgebliche Buch einzulassen.«

– Brian Sletten, Präsident von Bosatsu Consulting

Zu diesem Buch – sowie zu vielen weiteren O’Reilly-Büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei oreilly.plus+:

www.oreilly.plus

7. AUFLAGE

JavaScript –Das Handbuch für die Praxis

Meistern Sie die beliebte Sprachefür Web und Node.js

David Flanagan

Deutsche Übersetzung vonJørgen W. Lang und Jens Olaf Koch

David Flanagan

Lektorat: Ariane Hesse

Übersetzung: Jørgen W. Lang und Jens Olaf Koch

Korrektorat: Sibylle Feldmann, www.richtiger-text.de

Satz: III-satz, www.drei-satz.de

Herstellung: Stefanie Weidner

Umschlaggestaltung: Karen Montgomery, Michael Oreal, www.oreal.de

Bibliografische Information der Deutschen Nationalbibliothek

Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.

ISBN:

Print   978-3-96009-157-8

PDF    978-3-96010-491-9

ePub   978-3-96010-492-6

mobi   978-3-96010-493-3

7. Auflage 2021

Translation Copyright für die deutschsprachige Ausgabe © 2021 dpunkt.verlag GmbH

Wieblinger Weg 17

69123 Heidelberg

© 2021 dpunkt.verlag GmbH

Authorized German translation of the English edition of »JavaScript: The Definitive Guide«, 7E, ISBN 9781491952023 © 2020 David Flanagan.

This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same.

Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint »O’REILLY«.

O’REILLY ist ein Markenzeichen und eine eingetragene Marke von O’Reilly Media, Inc. und wird mit Einwilligung des Eigentümers verwendet.

Hinweis:

Dieses Buch wurde auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie.

Schreiben Sie uns:

Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: [email protected]de.

Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.

Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.

Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag noch Übersetzer können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.

5 4 3 2 1 0

Meinen Eltern, Donna und Matt, voller Liebe und Dankbarkeit.

Inhalt

Vorwort

1Einführung in JavaScript

1.1JavaScript erkunden

1.2Hello World

1.3Ein Rundgang durch JavaScript

1.4Beispiel: Häufigkeitshistogramme

1.5Zusammenfassung

2Die lexikalische Struktur

2.1Der Text eines JavaScript-Programms

2.2Kommentare

2.3Literale

2.4Identifier und reservierte Wörter

2.5Unicode

2.6Optionale Semikola

2.7Zusammenfassung

3Typen, Werte und Variablen

3.1Übersicht und Definitionen

3.2Zahlen

3.3Text

3.4Boolesche Werte

3.5null und undefined

3.6Symbole

3.7Das globale Objekt

3.8Unveränderbare primitive Werte und veränderbare Objektreferenzen

3.9Typumwandlungen

3.10Variablendeklaration und -zuweisung

3.11Zusammenfassung

4Ausdrücke und Operatoren

4.1Elementare Ausdrücke

4.2Initialisierungsausdrücke von Objekten und Arrays

4.3Ausdrücke zur Funktionsdefinition

4.4Ausdrücke für den Eigenschaftszugriff

4.5Aufrufausdrücke

4.6Ausdrücke zur Objekterstellung

4.7Operatoren im Überblick

4.8Arithmetische Ausdrücke

4.9Relationale Ausdrücke

4.10Logische Ausdrücke

4.11Zuweisungsausdrücke

4.12Auswertungsausdrücke

4.13Weitere Operatoren

4.14Zusammenfassung

5Anweisungen

5.1Anweisungsausdrücke

5.2Zusammengesetzte und leere Anweisungen

5.3Bedingungen

5.4Schleifen

5.5Sprünge

5.6Verschiedene Anweisungen

5.7Deklarationen

5.8Zusammenfassung

6Objekte

6.1Einführung in Objekte

6.2Objekte erstellen

6.3Eigenschaften abfragen und zuweisen

6.4Eigenschaften löschen

6.5Eigenschaften prüfen

6.6Eigenschaften aufzählen

6.7Objekte erweitern

6.8Objekte serialisieren

6.9Objektmethoden

6.10Erweiterte Syntax für Objektliterale

6.11Zusammenfassung

7Arrays

7.1Arrays erstellen

7.2Array-Elemente lesen und schreiben

7.3Sparse-Arrays

7.4Array-Länge

7.5Array-Elemente hinzufügen und löschen

7.6Über Arrays iterieren

7.7Mehrdimensionale Arrays

7.8Array-Methoden

7.9Arrayartige Objekte

7.10Strings als Arrays

7.11Zusammenfassung

8Funktionen

8.1Funktionen definieren

8.2Funktionen aufrufen

8.3Funktionsargumente und -parameter

8.4Funktionen als Werte

8.5Funktionen als Namensräume

8.6Closures

8.7Funktionseigenschaften, -methoden und -konstruktoren

8.8Funktionale Programmierung

8.9Zusammenfassung

9Klassen

9.1Klassen und Prototypen

9.2Klassen und Konstruktoren

9.3Klassen erstellen mit dem Schlüsselwort class

9.4Existierende Klassen um Methoden erweitern

9.5Subklassen

9.6Zusammenfassung

10Module

10.1Module mit Klassen, Objekten und Closures

10.2Module in Node

10.3Module in ES6

10.4Zusammenfassung

11Die JavaScript-Standardbibliothek

11.1Sets und Maps

11.2Typisierte Arrays und binäre Daten

11.3Mustererkennung mit regulären Ausdrücken

11.4Datum und Uhrzeit

11.5Fehlerklassen

11.6Serialisierung und Parsing mit JSON

11.7Die Internationalisierungs-API

11.8Die Console-API

11.9URL-APIs

11.10Timer

11.11Zusammenfassung

12Iteratoren und Generatoren

12.1Wie Iteratoren funktionieren

12.2Iterierbare Objekte implementieren

12.3Generatoren

12.4Erweiterte Generatorfunktionen

12.5Zusammenfassung

13Asynchrones JavaScript

13.1Asynchrone Programmierung mit Callbacks

13.2Promises

13.3async und await

13.4Asynchrone Iteration

13.5Zusammenfassung

14Metaprogrammierung

14.1Eigenschaftsattribute

14.2Objekte erweitern

14.3Das prototype-Attribut

14.4Wohlbekannte Symbole

14.5Template-Tags

14.6Die Reflect-API

14.7Proxy-Objekte

14.8Zusammenfassung

15JavaScript im Webbrowser

15.1Grundlagen der Webprogrammierung

15.2Events

15.3Dokumente skripten

15.4CSS skripten

15.5Dokumentgeometrie und Scrolling

15.6Webkomponenten

15.7SVG: Scalable Vector Graphics

15.8Grafiken auf einem <canvas>

15.9Audio-APIs

15.10Location-Objekt, Navigation und Browserverlauf

15.11Netzwerkoperationen

15.12Clientseitige Speicherung

15.13Worker-Threads und Messaging

15.14Beispiel: Die Mandelbrot-Menge

15.15Zusammenfassung und Vorschläge für die weitere Lektüre

16Serverseitiges JavaScript mit Node

16.1Grundlagen der Node-Programmierung

16.2Node ist standardmäßig asynchron

16.3Buffer

16.4Events und EventEmitter

16.5Datenströme

16.6Details zu Prozessen, CPU und Betriebssystem

16.7Mit Dateien arbeiten

16.8HTTP-Clients und -Server

16.9Nicht-HTTP-basierte Netzwerkserver und -clients

16.10Mit Kindprozessen arbeiten

16.11Worker-Threads

16.12Zusammenfassung

17JavaScript-Werkzeuge und -Erweiterungen

17.1Linting mit ESLint

17.2JavaScript-Formatierung mit Prettier

17.3Unit-Tests mit Jest

17.4Paketverwaltung mit npm

17.5Code-Bundling

17.6Transpilierung mit Babel

17.7JSX: Markup-Ausdrücke in JavaScript

17.8Typüberprüfung mit Flow

17.9Zusammenfassung

Index

Vorwort

Dieses Buch behandelt die Programmiersprache JavaScript und die von Webbrowsern und von Node implementierten JavaScript-APIs. Ich habe es für Leser geschrieben, die bereits etwas Programmiererfahrung haben und JavaScript lernen wollen. Es ist aber auch für Programmierer gedacht, die JavaScript bereits verwenden, ihr Wissen darüber aber erweitern und die Sprache wirklich beherrschen wollen. In diesem Buch möchte ich JavaScript umfassend und eindeutig dokumentieren und detailliert in die wichtigsten client- und serverseitigen APIs einführen, die für JavaScript-Programme zur Verfügung stehen. Deshalb ist es ein langes und ausführliches Buch. Ich hoffe aber, dass sein gründliches Studium belohnt wird und sich die Zeit, die Sie mit der Lektüre verbringen, in Form einer höheren Produktivität beim Programmieren schnell wieder bezahlt macht.

Frühere Ausgaben dieses Buchs enthielten einen umfassenden Referenzteil. Ich halte es aber nicht mehr für sinnvoll, dieses Material in gedruckter Form bereitzustellen, weil man heutzutage aktuelles Referenzmaterial jederzeit online findet. Wenn Sie etwas nachschlagen müssen, das mit dem Sprachkern oder clientseitigem JavaScript zu tun hat, empfehle ich Ihnen, die MDN-Website (https://developer.mozilla.org) zu besuchen. Für serverseitige Node-APIs sollten Sie direkt zur Quelle gehen und die Node.js-Referenzdokumentation (https://nodejs.org/api) konsultieren.

Konventionen, die in diesem Buch verwendet werden

In diesem Buch verwende ich die folgenden typografischen Konventionen:

Kursiv

Wird zur Hervorhebung und zur Angabe der ersten Verwendung eines Begriffs, aber auch für E-Mail-Adressen, URLs und Dateinamen verwendet.

Nicht proportional

Wird in JavaScript-Code sowie in CSS- und HTML-Listings verwendet – und im Allgemeinen für alles, was Sie beim Programmieren in genau der angegebenen Form per Tastatur eingeben würden.

Nicht proportional kursiv

Wird gelegentlich bei der Erläuterung der JavaScript-Syntax verwendet.

Nicht proportional fett

Zeigt Befehle oder anderen Text an, der vom Benutzer wortgetreu eingegeben werden muss.

Dieses Element kennzeichnet einen allgemeinen Hinweis.

Dieses Element weist auf eine Warnung hin.

Beispielcode

Ergänzendes Material (Codebeispiele, Übungen usw.) für dieses Buch stehen zum Download bereit unter:

https://oreil.ly/javascript_defgd7

Dieses Buch soll Sie bei der Erledigung Ihrer Aufgaben unterstützen. Wenn in diesem Buch Beispielcode angeboten wird, können Sie diesen in Ihren Programmen und Ihrer Dokumentation verwenden. Sie brauchen uns nicht um Erlaubnis zu bitten, es sei denn, Sie reproduzieren einen wesentlichen Teil des Codes. Beispielsweise erfordert das Schreiben eines Programms, das mehrere Codeblöcke aus diesem Buch verwendet, keine Genehmigung. Der Verkauf oder Vertrieb von Beispielen aus O’Reilly-Büchern benötigt dagegen eine Genehmigung. Für die Beantwortung einer Frage, indem aus diesem Buch oder dem Beispielcode zitiert wird, ist keine Genehmigung erforderlich. Das Einbinden einer beträchtlichen Menge an Beispielcode aus diesem Buch in die Dokumentation Ihres Produkts erfordert dagegen eine Genehmigung.

Wir freuen uns über eine Quellenangabe, verlangen sie aber im Allgemeinen nicht. Eine Quellenangabe umfasst in der Regel den Titel, den Autor, den Verlag und die ISBN, zum Beispiel: »JavaScript: The Definitive Guide, siebte Auflage, von David Flanagan (O’Reilly). Copyright 2020 David Flanagan, ISBN 9781491952023«.

Wenn Sie glauben, dass Ihre Verwendung der Codebeispiele über einen fairen Gebrauch oder die oben erteilten Genehmigungen hinausgeht, können Sie uns unter [email protected] gern kontaktieren.

O’Reilly Online-Lernen

Seit mehr als 40 Jahren bietet O'Reilly Media (https://oreilly.com) Technologie- und Businesstraining sowie Wissen und Einsichten, um Unternehmen zum Erfolg zu verhelfen.

Unser einzigartiges Netzwerk aus Experten und Innovatoren teilt sein Wissen und seine Expertise in Büchern, Artikeln und auf unserer Onlinelernplattform. Die Onlinelernplattform von O’Reilly bietet Ihnen On-Demand-Zugriff auf Live-Schulungen, detaillierte Lernpfade, interaktive Codierumgebungen sowie eine umfangreiche Sammlung an Texten und Videos von O’Reilly und über 200 anderen Verlagen. Für weitere Informationen besuchen Sie bitte https://oreilly.com.

Danksagungen

An der Entstehung dieses Buchs waren viele Personen beteiligt. Ich möchte meiner Lektorin Angela Rufino dafür danken, dass sie mich auf Kurs gehalten hat, und für ihre Geduld angesichts meiner versäumten Termine. Danke auch an meine technischen Gutachter Brian Sletten, Elisabeth Robson, Ethan Flanagan, Maximiliano Firtman, Sarah Wachs und Schalk Neethling. Ihre Kommentare und Vorschläge haben deutlich zur Qualität dieses Buchs beigetragen.

Das Produktionsteam von O’Reilly hat seine gewohnt gute Arbeit geleistet: Kristen Brown leitete den Produktionsprozess, Deborah Baker fungierte als Produktionsredakteurin, Rebecca Demarest war für die Abbildungen zuständig und Judy McConville für den Index.

Zu den Lektorinnen, Gutachtern und Mitwirkenden früherer Ausgaben dieses Buchs gehören: Andrew Schulman, Angelo Sirigos, Aristoteles Pagaltzis, Brendan Eich, Christian Heilmann, Dan Shafer, Dave C. Mitchell, Deb Cameron, Douglas Crockford, Dr. Tankred Hirschmann, Dylan Schiemann, Frank Willison, Geoff Stearns, Herman Venter, Jay Hodges, Jeff Yates, Joseph Kesselman, Ken Cooper, Larry Sullivan, Lynn Rollins, Neil Berkman, Mike Loukides, Nick Thompson, Norris Boyd, Paula Ferguson, Peter-Paul Koch, Philippe Le Hegaret, Raffaele Cecco, Richard Yaker, Sanders Kleinfeld, Scott Furman, Scott Isaacs, Shon Katzenberger, Terry Allen, Todd Ditchendorf, Vidur Apparao, Waldemar Horwat und Zachary Kessin.

Das Schreiben dieser siebten Ausgabe hielt mich viele lange Nächte von meiner Familie fern, bei der ich mich in Liebe dafür bedanken möchte, dass sie meine Abwesenheiten ausgehalten hat.

– David Flanagan, im März 2020

KAPITEL 1

Einführung in JavaScript

JavaScript ist die Programmiersprache des Webs. Der weitaus größte Teil moderner Websites nutzt JavaScript, und alle modernen Webbrowser – auf Desktops, Tablets und Smartphones – besitzen JavaScript-Interpreter, was JavaScript zur am häufigsten eingesetzten Programmiersprache überhaupt macht. In den letzten zehn Jahren hat Node.js die JavaScript-Programmierung auch außerhalb von Webbrowsern ermöglicht, und der dramatische Erfolg von Node hat dazu geführt, dass JavaScript nun auch die unter Softwareentwicklern am häufigsten verwendete Programmiersprache ist. Egal ob Sie bei null anfangen oder JavaScript bereits professionell einsetzen, dieses Buch wird Ihnen dabei helfen, diese Sprache zu beherrschen.

Wenn Sie schon mit anderen Programmiersprachen vertraut sind, ist es vielleicht hilfreich, zu wissen, dass es sich bei JavaScript um eine dynamische, interpretierte Hochsprache handelt, die für objektorientierte wie auch funktionale Programmierstile sehr gut geeignet ist. Die Variablen von JavaScript sind untypisiert. Ihre Syntax basiert lose auf Java, aber die Sprachen sind ansonsten nicht miteinander verwandt. JavaScript leitet seine erstklassigen Funktionen von Scheme und seine prototypenbasierte Vererbung von der wenig bekannten Sprache Self ab. Sie müssen aber diese Sprachen weder kennen noch auch nur mit den Begriffen vertraut sein, um dieses Buch verwenden und JavaScript erlernen zu können.

Der Name »JavaScript« ist leicht irreführend. Abgesehen von einer oberflächlichen Ähnlichkeit der Syntax unterscheidet sich JavaScript komplett von Java. Darüber hinaus ist JavaScript längst über seine Wurzeln als Skriptsprache hinausgewachsen und zu einer robusten und effizienten Allzwecksprache geworden, die sich für ernsthaftes Softwareengineering und für Projekte mit riesigen Codebasen eignet.

Damit man eine Sprache nutzen kann, muss sie eine Plattform- bzw. Standardbibliothek besitzen, um zum Beispiel die Ein- und Ausgabe zu ermöglichen. Der Sprachkern von JavaScript legt eine minimale API für den Umgang mit Zahlen, Text, Arrays, Sets, Maps usw. fest, besitzt aber keine Ein- und Ausgabefunktionalität. Diese (und fortgeschrittenere Features der Bereiche Netzwerk, Speicher und Grafik) liegen ganz in der Verantwortung der Hostumgebung, in die JavaScript eingebettet ist.

JavaScript: Namen, Versionen und Modi

JavaScript wurde in den frühen Tagen des Webs bei Netscape entwickelt, und die Bezeichnung JavaScript selbst ist ein von Sun Microsystems (jetzt Oracle) lizenziertes Warenzeichen, das zur Beschreibung der Implementierung der Sprache durch Netscape (jetzt Mozilla) verwendet wird. Netscape hatte die Sprache zur Standardisierung bei der ECMA eingereicht – der European Computer Manufacturers Association –, und aufgrund von Markenrechtsproblemen erhielt die standardisierte Version der Sprache den sperrigen Namen »ECMAScript«. In der Praxis spricht aber eigentlich jeder von JavaScript. In diesem Buch werden der Name ECMAScript und die Abkürzung ES benutzt, um speziell auf den Sprachstandard und auf bestimmte Versionen dieses Standards hinzuweisen.

In den 2010er-Jahren wurde von allen Webbrowsern überwiegend Version 5 des ECMAScript-Standards unterstützt. Deshalb wird in diesem Buch ES5 als die Kompatibilitäts-Baseline betrachtet, sodass frühere Versionen der Sprache nicht behandelt werden. ES6 wurde 2015 veröffentlicht und fügte wichtige neue Funktionen – darunter die Klassen- und Modulsyntax – hinzu, die JavaScript von einer Skriptsprache in eine ernst zu nehmende, allgemein einsetzbare Sprache verwandelten, die sich auch für die Softwareentwicklung in großem Maßstab eignet. Seit ES6 wird die ECMAScript-Spezifikation jährlich überarbeitet, und die Versionen der Sprache – ES2016, ES2017, ES2018, ES2019 und ES2020 usw. – werden jetzt nach dem Jahr der Veröffentlichung benannt.

Während der Entwicklung von JavaScript versuchten die Sprachdesigner, Fehler in den frühen Versionen (vor ES5) zu korrigieren. Um die Abwärtskompatibilität aufrechtzuerhalten, ist es nicht möglich, ältere Sprachmerkmale (sogenannte Legacy-Features) zu entfernen, egal wie mangelhaft sie sind. Aber in ES5 und späteren Versionen können Programme in den Strict Mode – den strikten oder strict-Modus – von JavaScript wechseln, in dem eine Reihe von frühen Sprachfehlern korrigiert wurde. Um diesen Modus zu aktivieren, benutzt man die »use strict«-Anweisung, die in 5.6.3 besprochen wird. Dieser Abschnitt fasst auch die Unterschiede zwischen Legacy-JavaScript und JavaScript im strict-Modus zusammen. In ES6 und später aktiviert die Verwendung neuer Sprachfunktionen oft implizit den strict-Modus. Wenn Sie beispielsweise das ES6-Schlüsselwort class verwenden oder ein ES6-Modul erstellen, ist der gesamte Code innerhalb der Klasse oder des Moduls automatisch »strict«, und die alten, mangelhaften Funktionen sind in diesen Kontexten nicht verfügbar. In diesem Buch behandle ich auch die Legacy-Features von JavaScript, weise aber darauf hin, dass diese im strict-Modus nicht verfügbar sind.

Die ursprüngliche Hostumgebung für JavaScript war ein Webbrowser, und das ist immer noch die am häufigsten verwendete Ausführungsumgebung für JavaScript-Code. In einer Webbrowserumgebung kann JavaScript-Code Input durch Maus und Tastatur des Benutzers sowie durch HTTP-Anfragen erhalten, dem Nutzer aber auch per HTML und CSS Ausgaben anzeigen.

Seit 2010 ist eine weitere Hostumgebung für JavaScript-Code verfügbar. Anstatt JavaScript auf die Arbeit mit den APIs zu beschränken, die von einem Webbrowser bereitgestellt werden, gibt Node JavaScript Zugriff auf das gesamte Betriebssystem, sodass JavaScript-Programme Dateien lesen und schreiben, Daten über das Netzwerk senden und empfangen sowie HTTP-Anfragen stellen und bedienen können. Node ist eine beliebte Wahl zur Implementierung von Webservern und außerdem ein bequemes Werkzeug zum Schreiben einfacher Hilfsskripte als Alternative zu Shell-Skripten.

Der größte Teil dieses Buchs konzentriert sich auf die Programmiersprache JavaScript selbst, Kapitel 11 dokumentiert die JavaScript-Standardbibliothek, Kapitel 15 und 16 stellen Webbrowser sowie Node als Hostumgebungen vor.

In diesem Buch werden zunächst die Grundlagen beschrieben, um dann darauf aufbauend zu fortgeschritteneren Abstraktionen auf höherer Ebene überzugehen. Die Kapitel sind dazu gedacht, mehr oder weniger der Reihe nach gelesen zu werden. Aber das Erlernen einer neuen Programmiersprache ist kein linearer Prozess und ebenso wenig das Beschreiben einer Sprache: Jedes Sprachfeature hängt mit anderen Merkmalen zusammen, und dieses Buch ist mit Querverweisen gespickt – manchmal auf zurückliegende Kapitel, manchmal auf Material, das Sie noch nicht gelesen haben. Dieses Einführungskapitel gibt Ihnen einen ersten Überblick über die Sprache und führt in die wichtigsten Merkmale ein, die das Verständnis einer detaillierteren Behandlung in den folgenden Kapiteln erleichtern werden. Falls Sie bereits JavaScript programmieren, können Sie dieses Kapitel wahrscheinlich überspringen. (Obwohl Sie sicher gern Beispiel 1-1 am Ende des Kapitels lesen möchten, bevor Sie zu einem anderen Kapitel übergehen.)

1.1JavaScript erkunden

Wenn man eine neue Programmiersprache lernt, ist es wichtig, die Beispiele auszuprobieren, sie dann selbst zu modifizieren und erneut auszuprobieren, um das erworbene Verständnis der Sprache zu testen. Dazu benötigen Sie einen JavaScript-Interpreter.

Am einfachsten lassen sich ein paar Zeilen JavaScript ausprobieren, indem man – mit F12 bzw. Strg+Umschalt+I in Windows- bzw. Befehlstaste+Optionstaste+I in MacUmgebungen – die Entwicklertools in einem Webbrowser öffnet und auf die Registerkarte Konsole wechselt. Sie können dann in der Eingabeaufforderung Code eingeben und während der Eingabe die Ergebnisse sehen. Die Entwicklerwerkzeuge erscheinen oft als Fenster am unteren oder rechten Rand des Browserfensters, aber Sie können sie normalerweise als separate Fenster abkoppeln (wie in Abbildung 1-1 gezeigt), was oft recht bequem ist.

Abbildung 1-1: Die JavaScript-Konsole in den Entwicklertools von Firefox

Um JavaScript-Code auszuprobieren, können Sie auch Node von https://nodejs.org herunterladen und installieren. Sobald Node auf Ihrem System eingerichtet ist, öffnen Sie einfach ein Terminalfenster und geben node ein, um eine interaktive JavaScript-Sitzung wie diese zu starten:

1.2Hello World

Wenn Sie bereit sind, mit längeren Codeblöcken zu experimentieren, eignen sich diese zeilenbasierten interaktiven Umgebungen normalerweise nicht mehr besonders, und Sie werden es wahrscheinlich vorziehen, Ihren Code in einem Texteditor zu schreiben. Von dort aus können Sie den Code in die JavaScript-Konsole oder in eine Node-Sitzung kopieren. Oder Sie speichern Ihren Code in einer Datei (die herkömmliche Dateinamenserweiterung für JavaScript-Code lautet .js) und führen dann diese Datei mit Node aus:

$ node snippet.js

Wenn Sie Node in einer solchen nicht interaktiven Weise verwenden, wird der Wert des ausgeführten Codes nicht automatisch ausgegeben, sodass Sie das selbst vornehmen müssen. Verwenden Sie die Funktion console.log(), um Text und andere JavaScript-Werte in Ihrem Terminalfenster oder in der Konsole der Entwicklerwerkzeuge eines Browsers anzuzeigen – zum Beispiel indem Sie eine Datei hello.js erstellen, die folgende Codezeile enthält:

console.log("Hello World!");

Wenn Sie diese Datei mit nodehello.js ausführen, wird die Meldung »Hello World!« ausgegeben.

Möchten Sie die gleiche Nachricht in der JavaScript-Konsole eines Webbrowsers ausgeben, erstellen Sie eine neue Datei mit dem Namen hello.html und fügen diesen Text darin ein:

<script src="hello.js"></script>

Dann laden Sie hello.html in Ihren Webbrowser mit einer file://-URL wie dieser:

file:///Users/username/javascript/hello.html

Öffnen Sie nun das Fenster der Entwicklertools, um die Begrüßung in der Konsole zu sehen.

1.3Ein Rundgang durch JavaScript

Dieser Abschnitt enthält eine kurze Einführung in die JavaScript-Sprache anhand von Codebeispielen. Nach diesem einführenden Kapitel steigen wir richtig tief in JavaScript ein und beginnen damit ganz weit unten – Kapitel 2 erklärt Dinge wie JavaScript-Kommentare, Semikola und den Unicode-Zeichensatz. In Kapitel 3 wird es schon ein bisschen spannender: Es werden JavaScript-Variablen erklärt sowie die Werte, die man ihnen zuweisen kann.

Hier ist etwas Beispielcode, der die Höhepunkte dieser beiden Kapitel veranschaulicht:

Zwei weitere sehr wichtige Datentypen, mit denen man in JavaScript-Programmen arbeiten kann, sind Objekte und Arrays. Diese Typen behandeln wir in den Kapiteln 6 und 7, aber sie sind so wichtig, dass sie Ihnen in diesem Buch bereits viele Male zuvor begegnen werden:

Die hier dargestellte Syntax zur Auflistung von Array-Elementen innerhalb eckiger Klammern oder zur Abbildung von Bezeichnungen von Objekteigenschaften auf Eigenschaftswerte innerhalb geschweifter Klammern wird als Initialisierungsausdruck bezeichnet – und ist nur eines der Themen von Kapitel 4. Ein Ausdruck ist eine Phrase in JavaScript, die zu einem Wert ausgewertet werden kann. Beispielsweise ist die Verwendung von . und [], um auf den Wert einer Objekteigenschaft oder eines Array-Elements zu verweisen, ein Ausdruck.

Am häufigsten bildet man Ausdrücke in JavaScript, indem man Operatoren verwendet:

Betrachtet man JavaScript-Ausdrücke als Phrasen, wären JavaScript-Anweisungen ganze Sätze. Anweisungen sind das Thema von Kapitel 5. Ein Ausdruck ist, vereinfacht gesagt, etwas, das einen Wert liefert, aber nichts tut. Anweisungen hingegen liefern keinen Wert (zumindest keinen, der uns interessiert), ändern aber den Zustand. Oben haben Sie Variablendeklarationen und Zuweisungsanweisungen gesehen. Die andere große Kategorie von Anweisungen sind Kontrollstrukturen wie z.B. Bedingungen und Schleifen. Beispiele finden Sie weiter unten, nachdem wir die Funktionen behandelt haben.

Eine Funktion ist ein benannter und parametrisierter Block mit JavaScript-Code, den Sie einmal definieren und dann immer wieder aufrufen können. Funktionen werden formal erst in Kapitel 8 behandelt, aber wie Objekte und Arrays werden sie Ihnen auch vorher schon immer wieder mal begegnen. Hier ein paar einfache Beispiele:

In ES6 und späteren Versionen gibt es eine Kurzschriftsyntax für die Definition von Funktionen. Diese prägnante Syntax verwendet =>, um die Argumentliste vom Funktionskörper zu trennen, daher werden auf diese Weise definierte Funktionen als Pfeilfunktionen bezeichnet. Pfeilfunktionen werden am häufigsten eingesetzt, wenn eine unbenannte Funktion als Argument an eine andere Funktion übergeben werden soll. Verwendet man Pfeilfunktionen, sieht der vorhergehende Code so aus:

Wenn wir Funktionen mit Objekten verwenden, erhalten wir Methoden:

Hier erhalten Sie nun wie versprochen einige Funktionen, in denen als Anweisungen häufig genutzte JavaScript-Kontrollstrukturen vorkommen:

JavaScript unterstützt einen objektorientierten Programmierstil, unterscheidet sich aber deutlich von »klassischen« objektorientierten Programmiersprachen. Kapitel 9 behandelt die objektorientierte Programmierung in JavaScript im Detail anhand vieler Beispiele. Es folgt ein sehr einfaches Beispiel, das zeigt, wie Sie eine JavaScript-Klasse erstellen, die einen zweidimensionalen Punkt repräsentiert. Objekte, die Instanzen dieser Klasse sind, besitzen genau eine Methode namens distance(), die den Abstand des Punkts vom Ursprung berechnet:

So weit die Einführung in die grundlegende Syntax und die Fähigkeiten von JavaScript. Es folgen in sich abgeschlossene Kapitel, in denen weitere Sprachmerkmale behandelt werden:

Kapitel 10, Module

Zeigt, wie JavaScript-Code in einer Datei oder einem Skript Funktionen und Klassen verwenden kann, die in anderen Dateien oder Skripten definiert sind.

Kapitel 11, Die JavaScript-Standardbibliothek

Deckt die eingebauten Funktionen und Klassen ab, die allen JavaScript-Programmen zur Verfügung stehen. Dazu gehören wichtige Datenstrukturen wie Maps und Sets, eine Klasse für reguläre Ausdrücke für die Suche nach Textmustern, Funktionen zur Serialisierung von JavaScript-Datenstrukturen und vieles mehr.

Kapitel 12, Iteratoren und Generatoren

Erklärt, wie die for/of-Schleife funktioniert und wie Sie Ihre eigenen Klassen mit for/of iterierbar machen können. Daneben werden Generatorfunktionen und die yield-Anweisung behandelt.

Kapitel 13, Asynchrones JavaScript

Untersucht eingehend die asynchrone Programmierung in JavaScript, wobei Callbacks und Events, Promise-basierte APIs und die Schlüsselwörter async und await behandelt werden. Obwohl JavaScript im Kern nicht asynchron ist, sind asynchrone APIs Standard sowohl in Webbrowsern als auch in Node, und in diesem Kapitel werden die Techniken für die Arbeit mit diesen APIs erläutert.

Kapitel 14, Metaprogrammierung

Stellt eine Reihe fortgeschrittener Funktionen von JavaScript vor, die für Programmierer interessant sind, die Codebibliotheken schreiben, um diese anderen JavaScript-Programmierern zur Verfügung zu stellen.

Kapitel 15, JavaScript im Webbrowser

Stellt die Hostumgebung des Webbrowsers vor, erklärt, wie Webbrowser JavaScript-Code ausführen, und behandelt die wichtigsten der vielen von Webbrowsern definierten APIs. Dies ist bei Weitem das längste Kapitel des Buchs.

Kapitel 16, Serverseitiges JavaScript mit Node

Stellt die Hostumgebung von Node vor und behandelt das grundlegende Programmiermodell sowie die für das Verständnis wichtigsten Datenstrukturen und APIs.

Kapitel 17, JavaScript-Werkzeuge und -Erweiterungen

Deckt weitverbreitete Werkzeuge und Spracherweiterungen ab, die man kennen sollte und die Sie zu einem produktiveren Programmierer machen können.

1.4Beispiel: Häufigkeitshistogramme

Dieses Kapitel schließt mit einem kurzen, aber nicht trivialen JavaScript-Programm. Beispiel 1-1 ist ein Node-Programm, das Text von der Standardeingabe liest, aus diesem Text ein Häufigkeitshistogramm der vorkommenden Zeichen berechnet und dieses Histogramm ausgibt. Sie können das Programm wie folgt aufrufen, um die Zeichenhäufigkeit seines eigenen Quelltexts zu analysieren:

$ node charfreq.js < charfreq.js

T: ########### 11.22%

E: ########## 10.15%

R: ####### 6.68%

S: ###### 6.44%

A: ###### 6.16%

N: ###### 5.81%

O: ##### 5.45%

I: ##### 4.54%

H: #### 4.07%

C: ### 3.36%

L: ### 3.20%

U: ### 3.08%

/: ### 2.88%

Dieses Beispiel verwendet eine Reihe fortgeschrittener JavaScript-Funktionen und soll demonstrieren, wie JavaScript-Programme in der realen Welt aussehen können. Falls Sie den Code noch nicht vollständig verstehen, macht das nichts – ich verspreche Ihnen, dass in den folgenden Kapiteln alles erklärt wird.

Beispiel 1-1: Berechnung von Häufigkeitshistogrammen mit JavaScript

1.5Zusammenfassung

In diesem Buch wird JavaScript von Grund auf erklärt. Deshalb beginnen wir auch mit grundlegenden Dingen wie Kommentaren, Identifiern, Variablen und Datentypen, um dann zu Ausdrücken, Anweisungen, Objekten und Funktionen überzugehen und schließlich hochsprachliche Abstraktionen wie Klassen und Module zu behandeln. Ich nehme das Wort Handbuch im Titel dieses Buchs ernst: In den kommenden Kapiteln wird die Sprache in einer Detailgenauigkeit erklärt, die auf den ersten Blick abschreckend wirken mag. Um JavaScript wahrhaft zu beherrschen, muss man jedoch die Details verstehen, und ich hoffe, dass Sie sich die Zeit nehmen, dieses Buch von vorne bis hinten durchzulesen. Aber das muss natürlich nicht in einem Rutsch geschehen. Wenn Sie das Gefühl haben, sich in einem Abschnitt festgefahren zu haben, springen Sie einfach zum nächsten. Sie können später zu dem entsprechenden Abschnitt zurückkehren und sich den Details widmen, sobald Sie eine grundlegende Kenntnis der Sprache als Ganzes gewonnen haben.

KAPITEL 2

Die lexikalische Struktur

Die lexikalische Struktur einer Programmiersprache ist der Satz elementarer Regeln, der festlegt, wie Programme in dieser Sprache geschrieben werden müssen. Es ist die Syntax der untersten Ebene einer Sprache: Sie legt beispielsweise fest, wie Variablennamen gebildet werden, welche Zeichen Kommentare einleiten oder begrenzen und wie eine Programmanweisung von der nächsten unterschieden bzw. getrennt wird. Dieses kurze Kapitel dokumentiert die lexikalische Struktur von JavaScript. Es behandelt:

Groß-/Kleinschreibung, Leerzeichen und Zeilenumbrüche

Kommentare

Literale

Identifier und reservierte Wörter

Unicode

Optionale Semikola

2.1Der Text eines JavaScript-Programms

JavaScript ist eine Sprache, in der zwischen Groß- und Kleinschreibung unterschieden wird. Das bedeutet, dass Schlüsselwörter der Sprache, Variablen, Funktionsnamen und andere Identifier immer mit einer konsistenten Groß-/Kleinschreibung der enthaltenen Buchstaben eingegeben werden müssen. Das Schlüsselwort while muss zum Beispiel mit kleinem »w«, also »while«, eingegeben werden, nicht »While« oder »WHILE«. Dementsprechend wären online, Online, OnLine und ONLINE vier verschiedene Variablennamen.

Innerhalb von Programmen ignoriert JavaScript Leerzeichen, die zwischen Tokens (den lexikalischen Grundeinheiten) stehen. In den meisten Fällen ignoriert JavaScript auch Zeilenumbrüche (eine Ausnahme wird in 2.6 beschrieben). Da Sie also Leerzeichen und Zeilenumbrüche frei verwenden können, lassen sich Programme sauber und konsistent formatieren und einrücken, sodass der Code leicht lesbar und gut verständlich ist.

Zusätzlich zum regulären Leerzeichen (\u0020) erkennt JavaScript auch Tabulatoren, verschiedene ASCII-Steuerzeichen sowie unterschiedliche Unicode-Leerzeichen als Whitespace-Zeichen1. Als Zeilenabschlüsse versteht JavaScript Zeilenumbrüche (LF, Line Feed), Wagenrückläufe (CR, Carriage Return) und eine Wagenrücklauf-/Zeilenvorschubsequenz (CRLF: Carriage Return/Line Feed).

2.2Kommentare

JavaScript unterstützt zwei Arten von Kommentaren: Als Kommentar betrachtet und von JavaScript ignoriert wird Text, der zwischen der Zeichenfolge // und dem Ende einer Zeile steht, sowie Text, der zwischen den Zeichenfolgen /* und */ steht. Diese zweite Kommentarvariante darf mehrere Zeilen lang sein, aber nicht verschachtelt werden. Alle folgenden Codezeilen sind korrekte JavaScript-Kommentare:

// Dies ist ein einzeiliger Kommentar.

/* Das hier ist ebenfalls ein Kommentar. */ // Und hier ein weiterer.

/*

* Das ist ein mehrzeiliger Kommentar. Die zusätzlichen *-Zeichen am Anfang jeder

* Zeile sind nicht zwingend vorgeschrieben, aber sie sehen einfach cool aus –

* und verbessern die Lesbarkeit.

*/

2.3Literale

Ein Literal ist ein Datenwert, der direkt in einem Programm erscheint. Die folgenden Elemente sind jeweils Literale:

12 // Die Zahl zwölf.

1.2 // Die Zahl "eins Komma zwei".

"hello world" // Eine Zeichenfolge.

'Hi' // Eine weitere Zeichenfolge.

true // Ein boolescher Wert.

false // Ein weiterer boolescher Wert.

null // Abwesenheit eines Objekts.

Vollständige Informationen zu numerischen Literalen (auch Zahlliterale genannt) und String-Literalen finden Sie in Kapitel 3.

2.4Identifier und reservierte Wörter

Ein Identifier – der englische Originalbegriff Identifier wird im Deutschen ebenfalls häufig benutzt – ist schlicht ein Name. In JavaScript werden Identifier verwendet, um Konstanten, Variablen, Eigenschaften, Funktionen und Klassen zu benennen und um Labels für bestimmte Schleifen im JavaScript-Code bereitzustellen. Ein JavaScript-Identifier muss mit einem Buchstaben, einem Unterstrich (_) oder einem Dollarzeichen ($) beginnen. Danach folgende Zeichen können Buchstaben, Ziffern, Unterstriche oder Dollarzeichen sein. (Ziffern sind als erstes Zeichen nicht erlaubt, damit JavaScript auf einfache Weise Identifier und Zahlen unterscheiden kann.)

i

my_variable_name

v13

_dummy

$str

Wie auch in jeder anderen Programmiersprache reserviert JavaScript bestimmte Identifier für den Einsatz durch die Sprache selbst. Diese »reservierten Wörter« dürfen nicht als gewöhnliche Identifier verwendet werden. Sie sind im nächsten Abschnitt aufgeführt.

2.4.1Reservierte Wörter

Die folgenden Wörter sind Teil der Sprache JavaScript. Viele davon (wie if, while und for) sind reservierte Schlüsselwörter, die nicht als Namen von Konstanten, Variablen, Funktionen oder Klassen genutzt werden dürfen (obwohl sie alle als Namen von Eigenschaften innerhalb eines Objekts verwendet werden können). Andere (wie from, of, get und set) werden in bestimmten Kontexten eingesetzt, die syntaktisch eindeutig sind, und sind als Identifier erlaubt. Wieder andere Schlüsselwörter (wie z.B. let) können nicht vollständig reserviert werden, um die Rückwärtskompatibilität mit älteren Programmen zu erhalten. Aus diesem Grund bestimmen komplexe Regeln, wann sie als Identifier verwendet werden können. (let kann z.B. zusammen mit var außerhalb einer Klasse als Variablenname deklariert werden, nicht aber innerhalb mit const.) Am einfachsten ist es, alle diese Wörter als Identifier zu vermeiden – mit Ausnahme von from, set und target, die man problemlos und sicher einsetzen kann und deren Verwendung durchaus üblich ist.

as const export get null target void

async continue extends if of this while

await debugger false import return throw with

break default finally in set true yield

case delete for instanceof static try

catch do from let super typeof

class else function new switch var

JavaScript reserviert außerdem einige Wörter, die im Moment noch nicht offiziell Teil der Sprache sind, bei Bedarf aber in künftigen Versionen genutzt werden könnten.

enum implements interface package private protected public

Aus historischen Gründen sind arguments und eval unter bestimmten Umständen nicht als Identifier erlaubt – sie sollten am besten ganz vermieden werden.

2.5Unicode

JavaScript-Programme werden im Unicode-Zeichensatz geschrieben, und Sie können beliebige Unicode-Zeichen in Zeichenfolgen und Kommentaren verwenden. Aus Gründen der Portabilität und der einfachen Bearbeitung ist es üblich, in Identifiern lediglich ASCII-Buchstaben und -Ziffern zu verwenden. Das ist aber nur eine Programmierkonvention. Die Sprache erlaubt Unicode-Buchstaben, -Ziffern und -Ideogramme (aber keine Emojis) in Identifiern. Das bedeutet, dass man mathematische Symbole und Wörter aus nicht englischen Sprachen als Konstanten und Variablen verwenden kann:

2.5.1Unicode-Escape-Sequenzen

Es gibt Hard- und Software, die nicht in der Lage sind, alle Unicode-Zeichen anzuzeigen, als Eingabe entgegenzunehmen oder korrekt zu verarbeiten. Um Programmierer und Systeme zu unterstützen, die ältere Technologien verwenden, definiert JavaScript Escape-Sequenzen. Mit ihnen können Unicode-Zeichen mithilfe von ASCII-Zeichen geschrieben werden. Diese Unicode-Escape-Sequenzen beginnen mit den beiden Zeichen \u, gefolgt von entweder genau vier Hexadezimalziffern (unter Verwendung der Groß- oder Kleinbuchstaben A bis F) oder einer bis sechs Hexadezimalziffern in geschweiften Klammern. Unicode-Escape-Sequenzen dürfen in JavaScript-String-Literalen, Literalen für reguläre Ausdrücke und Identifiern (aber nicht in spracheigenen Schlüsselwörtern) vorkommen. Die Unicode-Escape-Sequenz für das Zeichen »é« ist beispielsweise \u00E9. Hier sind drei verschiedene Möglichkeiten, einen Variablennamen zu schreiben, der dieses Zeichen enthält:

Frühe Versionen von JavaScript unterstützten nur vierstellige Escape-Sequenzen. Die Version mit geschweiften Klammern wurde in ES6 eingeführt, um Unicode-Codepoints wie z.B. Emojis, die mehr als 16 Bit benötigen, besser zu unterstützen:

console.log("\u{1F600}"); // Gibt ein Smiley-Emoji aus.

Unicode-Escape-Sequenzen können auch in Kommentaren vorkommen. Dort werden sie aber einfach als ASCII-Zeichen behandelt (und nicht als Unicode), da Kommentare beim Ausführen des Codes ignoriert werden.

2.5.2Unicode-Normalisierung

Wenn Sie in Ihren JavaScript-Programmen Zeichen verwenden, die nicht zum ASCII-Standard gehören, müssen Sie sich bewusst sein, dass Unicode mehr als eine Art der Codierung desselben Zeichens erlaubt. Der aus einem Zeichen bestehende String »é« kann z.B. als einzelnes Unicode-Zeichen \u00E9 oder als reguläres ASCII-»e«, gefolgt von dem Zeichen \u0301, um den Accent aigu hinzuzufügen, dargestellt werden. In einem Texteditor werden beide Codierungen gleich aussehen. Dennoch verwenden sie unterschiedliche Binärcodierungen, und JavaScript erkennt diesen Unterschied, was zu sehr verwirrenden Problemen führen kann:

Der Unicode-Standard definiert die bevorzugte Codierung für alle Zeichen und legt ein Normalisierungsverfahren fest, um Text in eine kanonische Form umzuwandeln, die für Vergleiche geeignet ist. JavaScript geht davon aus, dass der Quellcode, den es interpretiert, bereits normalisiert wurde, und führt von sich aus keine Normalisierung durch. Wenn Sie planen, Unicode-Zeichen in Ihren JavaScript-Programmen zu verwenden, sollten Sie sicherstellen, dass Ihr Editor oder ein anderes Tool eine Unicode-Normalisierung Ihres Quellcodes durchführt. So können Sie verhindern, dass Sie am Ende unterschiedliche, aber visuell nicht unterscheidbare Identifier erhalten.

2.6Optionale Semikola

Wie viele andere Programmiersprachen verwendet auch JavaScript das Semikolon (;) zur Trennung von Anweisungen (siehe Kapitel 5). Das ist wichtig, um die Bedeutung Ihres Codes klarzustellen: Ohne Trennzeichen könnte das Ende einer Anweisung als Anfang der nächsten interpretiert werden oder umgekehrt. Normalerweise können Sie in JavaScript das Semikolon zwischen zwei Anweisungen weglassen, wenn diese Anweisungen in getrennten Zeilen stehen. (Am Ende eines Programms ist ebenfalls kein Semikolon vorgeschrieben. Das Gleiche gilt, wenn das folgende Token in einem Programm eine schließende geschweifte Klammer (}) ist.) Viele JavaScript-Programmierer (und ich im Code dieses Buchs) verwenden Semikola, um explizit das Ende von Anweisungen zu markieren, auch wenn es an diesen Stellen eigentlich nicht nötig ist. Bei einer anderen stilistischen Variante werden Semikola nach Möglichkeit weggelassen und nur in den wenigen Situationen verwendet, in denen sie tatsächlich vorgeschrieben sind. Für welche dieser Varianten Sie sich auch entscheiden – es gibt einige Auswirkungen optionaler Semikola, die Sie kennen sollten.

Betrachten Sie den folgenden Code. Da die beiden Anweisungen in zwei separaten Zeilen stehen, könnten Sie das erste Semikolon weglassen:

Schreibt man die Anweisungen jedoch folgendermaßen, ist das erste Semikolon unbedingt erforderlich:

Beachten Sie bitte, dass JavaScript nicht jeden Zeilenumbruch als Semikolon behandelt: Das passiert normalerweise nur, wenn es den Code nicht parsen kann, ohne ein implizites Semikolon hinzuzufügen. Formeller ausgedrückt (und mit drei Ausnahmen, die etwas später beschrieben werden): JavaScript behandelt einen Zeilenumbruch als Semikolon, wenn das nächste Nicht-Leerzeichen nicht als Fortsetzung der aktuellen Anweisung interpretiert werden kann. Betrachten Sie diesen Code:

let a

a

3

console.log(a)

JavaScript interpretiert ihn folgendermaßen:

Diese Regeln, anhand deren das Ende von Anweisungen erkannt wird, können zu einigen überraschenden Situationen führen. Folgender Code scheint aus zwei eigenständigen Anweisungen zu bestehen, die durch einen Zeilenumbruch getrennt werden:

Die Klammern zu Beginn der zweiten Zeile können aber auch als ein Funktionsaufruf auf dem f-Element der ersten Zeile interpretiert werden, sodass JavaScript den Code folgendermaßen lesen würde:

Es ist ziemlich unwahrscheinlich, dass eine solche Interpretation beabsichtigt ist. Hier ist also explizit ein Semikolon erforderlich, damit die Anweisungen tatsächlich separat behandelt werden.

Allgemein kann man sagen: Wenn eine Anweisung mit (, [, /, + oder - beginnt, besteht die Möglichkeit, dass sie als Fortsetzung der vorherigen Anweisung interpretiert wird. Anweisungen, die mit /, + oder - beginnen, sind in der Praxis recht selten, aber Anweisungen, die mit ( und [ beginnen, sind – zumindest in einigen JavaScript-Programmierstilen – keineswegs ungewöhnlich. Manche Programmierer stellen derartigen Anweisungen zur Sicherheit ein Semikolon voran, damit der Code auch dann noch korrekt funktioniert, wenn die vorhergehende Anweisung abgeändert und ein eventuell zuvor vorhandenes abschließendes Semikolon entfernt wird:

Es gibt drei Ausnahmen von der allgemeinen Regel, dass JavaScript Zeilenumbrüche als Semikolon interpretiert, wenn es die zweite Zeile nicht als Fortsetzung der Anweisung der ersten Zeile parsen kann. Die erste Ausnahme betrifft die Anweisungen return, throw, yield, break und continue (siehe Kapitel 5). Diese Anweisungen stehen häufig allein, manchmal aber folgt auf sie ein Identifier oder Ausdruck. Folgt nach einem dieser Wörter (vor irgendwelchen weiteren Tokens) ein Zeilenumbruch, interpretiert JavaScript diesen Zeilenumbruch immer als Semikolon. Schreiben Sie beispielsweise

return

true;

geht JavaScript davon aus, dass Sie Folgendes meinen:

return; true;

Wahrscheinlich haben Sie aber eher dies im Sinn gehabt:

return true;

Das bedeutet, dass Sie keinen Zeilenumbruch zwischen return, break oder continue und dem Ausdruck einfügen dürfen, der dem Schlüsselwort folgt. Machen Sie es trotzdem, wird die Ausführung Ihres Codes vermutlich fehlschlagen – und zwar auf eine Weise, die nur schwer zu durchschauen oder zu debuggen ist.

Die zweite Ausnahme betrifft die Operatoren ++ und -- (siehe 4.8). Diese Operatoren können als Präfixoperatoren vor oder als Postfixoperatoren nach einem Ausdruck eingesetzt werden. Möchten Sie einen dieser Operatoren als Postfixoperator benutzen, muss er in der gleichen Zeile stehen wie der Ausdruck, auf den er angewandt werden soll. Die dritte Ausnahme betrifft Funktionen, die mit der kompakten Pfeilnotation definiert sind: Der =>-Pfeil selbst muss in derselben Zeile wie die Parameterliste stehen.

2.7Zusammenfassung

In diesem Kapitel haben wir uns damit beschäftigt, wie die Syntax von JavaScript-Programmen auf der untersten lexikalischen Ebene aussieht. Das nächste Kapitel führt uns einen Schritt weiter und stellt die primitiven Datentypen und Werte (Zahlen, Zeichenketten usw.) vor, die als grundlegende Recheneinheiten für JavaScript-Programme dienen.

KAPITEL 3

Typen, Werte und Variablen

Computerprogramme arbeiten, indem sie Werte wie etwa die Zahl 3,14 oder den Text »Hallo Welt.« manipulieren. Die unterschiedlichen Arten von Werten, die in einer Programmiersprache repräsentiert und manipuliert werden können, bezeichnet man als Datentypen (oder kurz Typen), und der Satz unterstützter Datentypen ist eines der grundlegendsten Kennzeichen einer Programmiersprache. Wenn ein Programm einen Wert zur späteren Verwendung aufbewahren muss, weist es den Wert einer Variablen zu (oder »speichert« ihn in einer solchen). Variablen haben Namen, die wir in unseren Programmen verwenden, um auf Werte zu verweisen. Ein weiteres grundlegendes Kennzeichen einer Programmiersprache ist die Art und Weise, in der Variablen funktionieren. Dieses Kapitel erklärt Typen, Werte und Variablen in JavaScript. Es beginnt mit einem Überblick und einigen Definitionen.

3.1Übersicht und Definitionen

JavaScript-Datentypen lassen sich in zwei Kategorien unterteilen: primitive Typen und Objekttypen. Zu den primitiven Datentypen von JavaScript zählen Zahlen, Strings (im Deutschen auch oft Zeichenfolgen oder Zeichenketten genannt) und boolesche Wahrheitswerte. Ein wesentlicher Teil dieses Kapitels ist einer detaillierten Erklärung der numerischen (siehe 3.2) und String-Typen (siehe 3.3) in JavaScript gewidmet. Booleans werden in 3.4 behandelt.

Die speziellen JavaScript-Werte null und undefined sind primitive Werte, aber weder Zahlen noch Strings noch boolesche Werte. Beide werden in der Regel als einzige Mitglieder ihres jeweils eigenen speziellen Typs betrachtet. In 3.5 erfahren Sie mehr über null und undefined. In ES6 ist ein neuer spezieller Typ – das Symbol – hinzugekommen, mit dessen Hilfe Spracherweiterungen definiert werden können, ohne die Rückwärtskompatibilität zu beeinträchtigen. Symbole werden kurz in 3.6 behandelt.

Jeder JavaScript-Wert, der keine Zahl, kein String, kein boolescher Wert, kein Symbol, nicht null und nicht undefined ist, ist ein Objekt. Ein Objekt (das heißt ein Exemplar des Typs Object) ist eine Sammlung von Eigenschaften, die jeweils einen Namen und einen Wert haben (entweder einen primitiven Wert oder ein anderes Objekt). Ein ganz besonderes Objekt, das globale Objekt, wird in 3.7 behandelt. Eine übergreifendere und ausführlichere Behandlung von Objekten im Allgemeinen finden Sie in Kapitel 6.

Ein normales JavaScript-Objekt ist nichts anderes als eine ungeordnete Sammlung benannter Werte. In JavaScript gibt es außerdem eine spezielle Art von Objekt, das als Array bezeichnet wird. Ein Array ist eine geordnete Sammlung nummerierter Werte. Für die Arbeit mit Arrays – die einige spezielle Verhaltensweisen besitzen, die sie von gewöhnlichen Objekten unterscheiden – bietet JavaScript eine besondere Syntax. Arrays werden detailliert in Kapitel 7 behandelt.

Neben grundlegenden Objekten und Arrays definiert JavaScript eine Reihe weiterer nützlicher Objekttypen. Ein Set-Objekt stellt einen Satz von Werten dar, ein Map-Objekt dagegen stellt eine Zuordnung von Schlüsseln zu Werten dar. Verschiedene typisierte Arrays erleichtern Operationen auf Arrays von Bytes und anderen binären Daten. Der RegExp-Datentyp repräsentiert Textmuster und ermöglicht ausgeklügelte Vergleichs-, Such- und Ersetzungsoperationen auf Zeichenketten. Der Date-Datentyp stellt Datum und Uhrzeit dar und unterstützt rudimentäre Rechenoperationen mit Datumswerten. Der Fehlertyp Error und dessen Untertypen stellen Fehler dar, die beim Ausführen von JavaScript-Code auftreten können. Alle diese Typen werden in Kapitel 11 behandelt.

JavaScript unterscheidet sich von statischeren Sprachen dadurch, dass Funktionen und Klassen nicht nur Teil der Sprachsyntax, sondern selbst Werte sind, die von JavaScript-Programmen manipuliert werden können. Wie alle nicht primitiven JavaScript-Werte sind Funktionen und Klassen eine spezialisierte Art von Objekt. Sie werden ausführlich in den Kapiteln 8 und 9 behandelt.

Der JavaScript-Interpreter führt im Rahmen der Speicherverwaltung eine automatische Speicherbereinigung (Garbage Collection) durch. Als JavaScript-Programmierer muss man sich in der Regel also nicht um das Löschen oder die Deallokation von Objekten oder anderen Werten kümmern. Kann auf einen Wert nicht mehr zugegriffen werden – wenn ein Programm keine Möglichkeit mehr hat, darauf zu verweisen –, weiß der Interpreter, dass der Wert nicht mehr verwendet werden kann, und gibt automatisch den durch den Wert belegten Speicher frei. (Als JavaScript-Programmierer muss man darauf achten, dass Werte nicht versehentlich länger als nötig für das Programm »erreichbar« bleiben und der belegte Speicher deshalb nicht freigegeben werden kann.)

JavaScript unterstützt einen objektorientierten Programmierstil. Lax formuliert, bedeutet dies, dass man keine global definierten Funktionen nutzt, die auf Werten unterschiedlicher Typen operieren, sondern dass die Datentypen selbst Methoden für die Arbeit mit Werten definieren. Wollen wir beispielsweise die Elemente in einem Array a sortieren, übergeben wir a nicht an irgendeine sort()-Funktion. Stattdessen rufen wir die sort()-Methode von a auf:

a.sort(); // Die objektorientierte Version von sort(a).

Die Definition von Methoden wird in Kapitel 9 behandelt. Technisch gesehen, besitzen nur JavaScript-Objekte Methoden. Zahlen, Zeichenfolgen, boolesche Werte und Symbolwerte verhalten sich jedoch ebenfalls so, als besäßen sie Methoden. In JavaScript sind null und undefined die einzigen Werte, auf denen keine Methoden aufgerufen werden können.

Die Objekttypen von JavaScript sind veränderbar, die primitiven Typen sind unveränderbar. Der Wert eines veränderbaren Typs ist mutabel: Ein JavaScript-Programm kann die Werte von Objekteigenschaften und Array-Elementen ändern. Zahlen, boolesche Werte, Symbole, null und undefined sind unveränderbar – es ergäbe nicht einmal Sinn, von der Änderung des Werts einer Zahl zu sprechen. Man könnte Strings als Arrays von Zeichen betrachten und deshalb vielleicht erwarten, dass sie veränderbar seien. Strings sind in JavaScript aber unveränderbar: Sie können auf die Zeichen an einer beliebigen Position einer Zeichenfolge zugreifen, sie aber nicht verändern. Die Unterschiede zwischen veränderbaren und unveränderbaren Werten werden genauer untersucht in 3.8.

Konstanten und Variablen ermöglichen Ihnen, Namen zu verwenden, um in Ihren Programmen auf Werte zu verweisen. Konstanten werden mit const deklariert und Variablen mit let (oder in älterem JavaScript-Code mit var). JavaScript-Konstanten und -Variablen sind untypisiert: In den Deklarationen wird nicht angegeben, welche Art von Werten zugewiesen werden sollen. Die Variablendeklaration und -zuweisung wird in 3.10 behandelt.

Wie Sie bereits an dieser langen Einführung sehen können, ist dies ein umfassendes Kapitel, in dem viele grundlegende Details zur Darstellung und Manipulation von Daten in JavaScript erklärt werden. Legen wir direkt los mit den Einzelheiten zu Zahlen und Text.

3.2Zahlen

Der grundlegende numerische Typ in JavaScript, Number, wird verwendet, um Ganzzahlen und (näherungsweise) reelle Zahlen darzustellen. JavaScript stellt Zahlen im 64-Bit-Gleitkommaformat dar, das durch den IEEE-754-Standard1 definiert ist, und kann damit Zahlenwerte bis hinauf zu ±1.7976931348623157 × 10308 und bis hinab zu ±5 × 10–324 darstellen.

Das JavaScript-Zahlenformat ermöglicht Ihnen, alle ganzen Zahlen zwischen –9.007.199.254.740.992 (–253) und 9.007.199.254.740.992 (253) exakt festzuhalten, jeweils inklusive der Grenzen. Falls Sie größere ganzzahlige Werte als diese verwenden, können Sie in den letzten Ziffern an Genauigkeit verlieren. Beachten Sie jedoch, dass in JavaScript bestimmte Operationen (wie die Indizierung von Arrays und die in Kapitel 4 beschriebenen Bit-Operationen) mit 32-Bit-Ganzzahlen durchgeführt werden. Falls Sie größere Integer-Werte exakt darstellen müssen, schauen Sie sich bitte 3.2.5 an.

Erscheint eine Zahl unmittelbar in einem JavaScript-Programm, bezeichnet man sie als Zahlliteral