2
JavaScript für Entwickler
2.1Einleitung
Diese Kapitel richten sich an Leser, die Erfahrungen in der Programmierung in anderen Sprachen gesammelt haben. Wir starten nicht bei den absoluten Einsteigerthemen, sondern konzentrieren uns auf die Besonderheiten von JavaScript im Vergleich zu üblichen Programmiersprachen. Von diesen Besonderheiten hat JavaScript einige zu bieten, und darüber stolpern viele Entwickler beim Umstieg auf JavaScript.
Tipp: Starten mit JavaScript
Wer mit den Grundlagen, wie Syntax und Kontrollstrukturen, starten möchte, findet unter folgenden Links einen guten Einstieg:
Auf Wikipedia gibt es eine 5-Minuten-Einführung in JavaScript:
de.wikipedia.org/wiki/JavaScript#Sprachelemente
Sehr zu empfehlen ist folgendes kostenlose Online-Buch:
eloquentjavascript.net
2.2Dynamisches Web mit JavaScript
JavaScript wurde erfunden, um Webseiten dynamisch im Browser zu ändern und Interaktionen mit dem Benutzer zu realisieren. Das ist heute immer noch der Haupteinsatz. Der Standard ECMAScript (ECMA-262, Edition 5: www.ecma-international.org/
publications/standards/Ecma-262.htm) beschreibt die Sprache und ihre Elemente. An der Syntax ist die Verwandtschaft mit der Sprache »C« zu erkennen. Der Namensbestandteil »Java« ist eher als Marketing-Trick zu bezeichnen, denn die Gemeinsamkeiten mit Java sind gering.
JavaScript ist eine dynamisch typisierte, objektorientierte Scriptsprache. Das Besondere ist die hohe Flexibilität, die sich vor allem darin ausdrückt, dass es möglich ist verschiedene Arten der Programmierung anzuwenden: objektorientiert, prozedural und funktional. JavaScript entpuppt sich damit als Alleskönner. Das macht JavaScript aber leider nicht besonders einfach zu verstehen.
JavaScript kennt keine Sprachkonstrukte für Klassen, Interfaces und Vererbung, wie zum Beispiel Java. Alternativ bietet JavaScript Objekte (Instanzen) mit einem mächtigen Prototyp-Konzept. Sie sind ein flexibles Werkzeug, mit dem sich Vererbung nachbilden lässt.
Um komplexere Applikationen mit JavaScript bauen zu können, muss man sich intensiver mit der Sprache beschäftigen und mehr verstehen als die Deklaration von Variablen und die grundlegenden Kontrollstrukturen.
Die folgenden Abschnitte stellen einige der interessantesten Konzepte von JavaScript vor, um für die Implementierungen von Single-Page-Web-Apps in den nächsten Kapiteln gerüstet zu sein. Dabei werden wir auf einige Fehlerquellen und Fallstricke stoßen, auf die man bei der täglichen Arbeit immer wieder trifft.
Die meisten JavaScript-Beispiele können leicht in der Konsole von Google Chrome oder Firefox ausprobiert werden. Die Taste F12 öffnet die Entwickler-Tools und unter dem Reiter Konsole lassen sich direkt JavaScript-Befehle ausführen.
Bild 2.1: Die geöffnete Konsole in Google Chrome.
2.3Missverständnisse bei JavaScript
JavaScript hatte lange Zeit einen schlechten Ruf innerhalb der Entwicklergemeinde. In vielen Projekten wurde es ausschließlich eingesetzt, wenn die Aufgabe nicht anders zu lösen war. Das schlechte Bauchgefühl ist durchaus begründet, wie ein kleines Beispiel deutlich macht:
//Plus ist für Strings definiert. Die Ziffer wird konvertiert:
> console.log("42" + 7);
"427"
//Führt zur Konversion des 1. Operanden in eine Zahl:
> console.log("42" – 7);
35
Das Verhalten ist nicht konsistent. Der Plus-Operator ist für Zeichenketten sinnvoll einsetzbar: Die beiden Operanden werden als Strings verkettet. Der Minus-Operator verhält sich anders, da er für Zeichenketten nicht existiert. Der linke Operand wird in eine Zahl konvertiert und eine Subtraktion ausgeführt. Beides ist für sich genommen logisch, aber in der Kombination verwirrend.
Leider steht dieses Beispiel stellvertretend für viele weitere sonderbare Konstellationen, von denen einige in diesem Kapitel vorgestellt werden. Trotzdem ist JavaScript insgesamt besser als sein Ruf. Die nächsten Punkte stellen einige der typischen Missverständnisse bei JavaScript in ein klareres Licht.
2.3.1JavaScript kennt keine Datentypen
Das ist eine der bekanntesten Fehleinschätzungen, die immer wieder gegen die Sprache ins Feld geführt werden. Die Behauptung ist schlichtweg falsch. Schon die Existenz des typeof
-Operators sollte stutzig machen. Der Operator liefert den Datentyp eines Wertes oder einer Variable als Zeichenkette:
var bool1 = true;
console.log( typeof bool1 );
"boolean"
Dabei unterscheidet der typeof
-Operator vier grundlegende Fälle:
]Für undefinierte Werte oder Variablen ist die Rückgabe: undefined
.
]Die drei primitiven Datentypen liefern boolean
, number
oder string
.
]Wendet man typeof
auf eine Funktion an, erhält man function
.
]Für alle anderen Elemente liefert die Funktion object
. Dazu gehören ebenfalls Arrays und der Wert null
für nicht gesetzte Referenzen.
Die folgende Tabelle listet einige typische Beispiele mit den entsprechenden Rückgabewerten auf:
Typ des Operanden | Beispiel | Rückgabe |
Undefiniert | typeof newvar; | "undefined" |
Boolean | typeof true; | "boolean" |
String | typeof "Hallo"; | "string" |
Funktionen | typeof function add2() {}; | "function" |
Sonstige Objekte | typeof new String("Hallo"); | "object" |
| typeof new Boolean(true); | |
Array | typeof [ 1, 2, 3 ]; | "object" |
Einige Besonderheiten springen ins Auge: Funktionen haben offenbar eine große Bedeutung und stehen auf derselben Ebene wie Objekte. Funktionen werden wir intensiv weiter unten in einem separaten Abschnitt untersuchen.
Intuitiv würde man für den Wert null
die Rückgabe undefined
anstatt object
erwarten. Verwirrend ist die Unterscheidung zwischen den beiden Resultaten für den primitiven Typ string
und das Objekt String
, das über den Konstruktor (new
) erzeugt wurde. Intuitiv würde man für beide dasselbe Ergebnis erwarten.
Primitive Datentypen und Objekte
Die Unterscheidung zieht sich nicht in allen Fällen konsistent durch. So bietet das String-Objekt das Attribut length
, das die Länge der Zeichenkette liefert. Erstaunlich ist, dass die Methode analog auf den primitiven String anwendbar ist. Offenbar wandelt JavaScript den primitiven Datentyp automatisch in ein Objekt um. Man erhält den Eindruck, das Zusammenspiel der Typen sei nicht vollständig konsistent:
variable2 = new String("Beispieltext");
alert(variable2.length); // Ausgabe: 12
var variable = "Beispieltext";
alert(variable.length); // Ausgabe: 12
Wichtig ist in diesem Zusammenhang, dass Objekte als Referenz (»by reference«) an Funktionen übergeben werden. Eine Änderung am Objekt wirkt sich auf das übergebene Objekt aus und ist somit außerhalb der Funktion sichtbar. Primitive Typen werden als Wert (»by value«) übergeben. Änderungen sind nur im...