Web Engineering 1/Javascript 1
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
__NOTOC__
{{Ziele|
* Javascript als funktionsorientierte Sprache (ECMAScript)
* Gültigkeitsbereiche von Variablen
* Closure-Konzept
* Dynamische Typisierung von Variablen
* OOP mittels Prototypen
|
* Beherrschung der grundlegenden Javascript Syntax
* Kontrollierter Umgang mit globalen und lokalen Variablen
* Verwendung von Objekten (assoziativen Arrays)
* Intuitives Anwenden von Vergleichsoperatoren
* Erstellung und Manipulation von Prototypen
|
* Erstellung eines Sudoku-Spiel-Objekts zur Verwaltung
* Eigene "Klasse" für ein Sudoku-Feld, entsprechende Objekte im Sudoku-Spiel-Objekt
* Verknüpfung der Sudoku-Feld-Objekte mit dem entsprechenden Input-Feld
* Start-Knopf: Neues zufälliges Sudoku-Rätsel erzeugen (vorgegebene Zahlen dürfen nicht geändert werden)
}}
==Javascript Variablen==
Wie schon in den vorangegangen Kapiteln ersichtlich war, werden in Javascript Variablen mit dem Schlüsselwort <tt>var</tt> definiert. Dabei wird der Typ der Variablen nicht explizit festgelegt. Er ist dynamisch und steht erst mit der Zuweisung eines Wertes fest. Auch kann er sich jederzeit ändern durch Zuweisung eines Wertes von einem anderen Typ. Mit der Funktion <tt>typeof</tt> kann der momentane Typ einer Variablen ermittelt werden. Eine nicht initialisierte Variable hat immer den Wert <tt>undefined</tt>.
Mit <tt>var</tt> definierte Variablen gelten immer nur innerhalb Ihres jeweiligen Umfelds (Scope). In den meisten Fällen wird ein solches Umfeld durch die umgebenden geschweiften Klammern begrenzt. Im Unterschied zu vergleichsweise strikten Programmiersprachen wie Java spielt der Ort der Definition innerhalb dieses Umfelds keine Rolle. Allein das Vorhandensein der Variablen veranlasst den Javascript-Interpreter diese im gesamten Umfeld bereitzustellen.
{|
|style="width: 22em;vertical-align:top;"| <html>
<iframe width="400" height="340" src="//jsfiddle.net/pw_we1/wqxpeouy/embedded/js,html,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
</html>
|style="vertical-align:top;padding-left:1em;"|
* ''Erforschen Sie das Beispiel und erklären Sie:''
** ''Warum ändert der Aufruf von <tt>global</tt> den globalen Wert <tt>x</tt>?''
** ''Warum verändert <tt>a++</tt> in der Funktion <tt>local</tt> die globale Variable <tt>x</tt> nicht?''
** ''Warum verändert <tt>var x = 0;</tt> in der Funktion <tt>local</tt> die globale Variable <tt>x</tt> nicht?''
* ''Recherchieren Sie wie Arrays initialisiert und wie Elemente hinzugefügt werden''
* ''Initialisieren Sie <tt>x</tt> als Array und ersetzen Sie die Inkrementierung der Variablen durch das Hinzufügen von Elementen. Nehmen Sie die Länge der Arrays zur Berechnung der im Button-Text ausgegebenen Werte.''
* ''Erklären das unterschiedliche Verhalten (Hinweis: Value Type / Reference Type)''
|}
==Objects==
Neben dem <tt>Array</tt> bietet Javascript mit dem <tt>Object</tt> eine weitere dynamische Datenstruktur an. Im Prinzip handelt es sich dabei um nichts anderes als eine Liste von Name-Wert-Paaren. Aus diesem Grund wird ein Object auch oft als ''assoziatives Array'' bezeichnet. Die Javascript Syntax hält jedoch mit der Punktnotation eine erweiterte Zugriffsmöglichkeit bereit die eine Art Objektorientierung suggeriert. Das setzt sich darin fort, dass die Schlüssel des assoziativen Arrays ''Property'' genannt werden. Als Schlüssel werden ausschließlich Zeichenketten unterstützt. Werden bei der Programmierung Elemente anderen Typs verwendet, so wird automatisch nur deren String-Repräsentation zum Schlüssel und nicht das Element selbst.
{|
|style="width: 22em;vertical-align:top;"| <html>
<iframe width="400" height="270" src="//jsfiddle.net/pw_we1/j014dw2r/embedded/js,html,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
</html>
|style="vertical-align:top;padding-left:1em;"|
* ''Nutzen Sie das Eingabefeld um die verschiedenen Möglichkeiten des Zugriffs auf Objekteigenschaften zu erproben''
* ''Erzeugen Sie auch neue Eigenschaften.''
* ''Die Zugriffsarten sind unterschiedlich mächtig. Finden Sie heraus was mit dem Punkt-Operator nicht möglich ist''
* ''Erzeugen Sie neue Objekte als Eigenschaften und greifen Sie auf diese zu''
* ''Erzeugen Sie eine Objekt-Rekursion (eine Eigenschaft verweist auf das Objekt welches diese enthält). Zeigen Sie, dass Eigenschaft und Objekt identisch sind.''
* ''Recherchieren Sie eine Möglichkeit die Eigenschaften eines Objekts zu iterieren. Vergleichen Sie die Geschwindigkeit der Iteration mit der eines Arrays und erklären Sie das Ergebnis.''
|}
==Vergleichsoperatoren==
Aufgrund der dynamischen Typisierung von Variablen gibt es in Javascript eine Besonderheit bei den Vergleichsoperatoren. Die bekannten Operatoren <tt>==</tt> bzw. <tt>!=</tt> führen hier einen weniger strikten Vergleich aus. Werden Variablen unterschiedlichen Typs verglichen, so werden diese zunächst in einen gleichen Typ konvertiert (siehe [http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 The Abstract Equality Comparison Algorithm]). Um sicherzustellen, dass zwei Variablenwerte auch den gleichen Typ haben, müssen die strikten Vergleichsoperatoren <tt>===</tt> und <tt>!==</tt> verwendet werden. Werden Objekte miteinander verglichen, so gelten diese bei beiden Operator-Typen nur dann als identisch wenn es sich um die selben (nicht die gleichen) Objekte handelt.
{|
|style="width: 22em;vertical-align:top;"| <html>
<iframe width="370" height="300" src="//jsfiddle.net/pw_we1/yco7oez6/embedded/js,html,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
</html>
|style="vertical-align:top;padding-left:1em;"|
* ''Führen Sie verschiedene Vergleiche aus. Finden heraus wann der weniger strikte Vergleich problematisch wird''
* ''Vergleichen Sie auch die Array-Elemente und Objekt-Eigenschaften miteinander''
* ''Fügen Sie <tt>obj1</tt> sowohl <tt>arr1</tt> als auch <tt>arr2</tt> hinzu und vergleichen Sie die hinzugefügten Array-Elemente''
* ''Machen Sie sich den Unterschied zwischen Wert-Typen und Referenz-Typen klar''
* ''Jedes Objekt hat eine Funktion <tt>toString()</tt>. Vergleichen Sie deren Rückgabewerte von <tt>obj1</tt> und <tt>obj2</tt>''
* ''Vergleichen Sie auch die <tt>toString</tt> Funktionen von <tt>obj1</tt> und <tt>obj2</tt>. Entspricht das Ihren Erwartungen?''
|}
==OOP mit Javascript==
Das Konzept der objektorientierten Programmierung basiert darauf, dass auf Basis struktureller Vorgaben (Klassen) Objekte dynamisch erzeugt werden können (Instanzen), die einen eigenen Zustand haben und Methoden bereitstellen, wobei übergeordnete Strukturvorgaben (Basisklassen) integriert sind.
Mit dem Schlüsselwort <tt>new</tt> können in Javascript solche Objekte erzeugt werden. Als Strukturvorgabe werden Funktionen verwendet. Bei Instanziierung dient die Funktion als Vorlage und Konstruktor für das neue Objekt. Sämtliche in der Funktion definierten Variablen und Unterfunktionen stehen dann innerhalb des Objekts gekapselt zur Verfügung. Um öffentliche Funktionen und Variablen zu definieren, kann das Schlüsselwort <tt>this</tt> verwendet werden.
Im Prinzip ist damit das Konzept von Klassen und Instanzen umgesetzt. Aber jedes instanziierte Objekt trägt so auch sämtliche Definitionen der Vorgabefunktion mit sich. Strukturelle Änderungen, so wie sie in Javascript üblich sind, betreffen damit immer nur die jeweilige Instanz. Das in Javascript implementierte Prototypen-Konzept bietet hier weitere Möglichkeiten. Jede Funktion besitzt eine Eigenschaft <tt>prototype</tt>. Diese hält ein Objekt das all seine Eigenschaften und Methoden an die Funktion weitergibt. Wird dieses Objekt um Funktionen und/oder Variablen erweitert, so stehen diese direkt am instanziierten Objekt zur Verfügung (wie mit <tt>this</tt> definierte Eigenschaften). Der Unterschied besteht nun darin, dass alle instanziierten Objekte nicht nur den gleichen, sondern den selben Prototyp benutzen. Prototyp-Funktionen gibt es damit nur ein einziges Mal (unabhängig von der Anzahl der Instanzen) und Änderungen am Prototyp gehen augenblicklich auf alle Instanzen über.
Die Funktionsweise der Prototypen erlaubt damit auch das Prinzip der Vererbung umzusetzen. Im Unterschied zur üblichen objektorientierten Programmierung erbt hier ein Objekt von einem anderen Objekt. Realisiert wird die Vererbung durch Überschreiben der <tt>prototype</tt> Eigenschaft mit dem Basisobjekt.
{|
|style="width: 23em;vertical-align:top;"|<html>
<iframe width="370" height="380" src="//jsfiddle.net/pw_we1/4y8rogoj/embedded/js,html,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>
</html>
|style="vertical-align:top;padding-left:1em;"|
* ''Analysieren Sie das Beispiel. Erschließen Sie in welchem Rahmen die jeweiligen Variablen und Funktionen gelten und erproben Sie Ihre Annahmen.''
* ''Machen Sie sich bewusst, was der <tt>new</tt> Operator eigentlich tut''
* ''Modifizieren Sie das Beispiel und erzeugen Sie ein zweites <tt>Obj</tt> Objekt. Vergleichen Sie die Eigenschaften und Funktionen der Objekte.''
* ''Funktionen am <tt>prototype</tt> sind direkt am Objekt verfügbar. Was passiert wenn Sie eine gleichnamige Funktion in der Objektdefinition deklarieren?''
* ''Das Konzept der Vererbung basiert darauf, dass eine abgeleitete Klasse die Methoden und Eigenschaften ihrer Basisklasse erhält. Bewerten Sie in dieser Hinsicht die Möglichkeiten der Eigenschaft <tt>prototype</tt>.''
* ''Was passiert wenn dem <tt>prototype</tt> von Objekt A ein anderes Objekt B zugewiesen wird? Experimentieren Sie.''
* ''Recherchieren Sie die Eigenschaft <tt>constructor</tt> von <tt>prototype</tt> und dessen Bedeutung bei der Realisierung der Vererbung''
* ''Mit ECMAScript 2015 (ES6) wurden neue syntaktische Hilfsmittel zur objektorientierten Programmierung mit Javascript eingeführt. Recherchieren Sie die Verwendung von <tt>class</tt>, <tt>extends</tt>, <tt>super</tt> sowie die Syntax zur Definition von Gettern und Settern.''
* ''Setzen Sie die Übungen zur OOP unter Verwendung der alternativen Syntax um.''
|}
==Projekt und weitere Übungen==
{{Projekt|
Erstellen Sie ein objektorientiertes Modell zur Verwaltung des Spiels und verknüpfen Sie es auf geeignete Weise mit den HTML Elementen. Füllen Sie das Sudoku bei Betätigung des Start-Buttons nun mit einer gültigen Zahlenbelegung sodass es eindeutig lösbar ist. Die übliche Verfahrensweise bei der Generierung eines Sudoku besteht aus zwei Schritten:
# Erzeugung eines vollständig mit Zufallszahlen ausgefüllten Sudokus, wobei die Sudoku-Regeln nicht verletzt werden
# Entfernung von Werten an zufälligen Positionen, solange das Sudoku eindeutig lösbar bleibt
Für Punkt 1 ist ein Backtracking Algorithmus notwendig. Wenn für ein Feld keine der neun Zahlen in Frage kommt, dann muss ein vorher bereits festgelegtes Feld noch einmal verändert werden.
Ein Sudoku ist eindeutig lösbar, wenn es zu jedem Zeitpunkt immer mindestens ein Feld gibt, dem nur eine einzige Zahl zugeordnet werden kann.
Beispiellösung <document>WE1-P6.zip</document>
}}
# Schreiben Sie ein Programm, das die Quadrate der Zahlen von 0 bis 9 untereinander in einer HTML-Seite ausgibt. Entwickeln Sie im Browser (Entwickler-Tools, JavaScript-Konsole).<br>Hinweis: Benutzen Sie eine for-Schleife, die von 0 bis 9 hochzählt, den Zähler quadriert und das Ergebnis mit document.writeln() ausgibt.
# Schreiben Sie (ohne Browser) ein Programm, das die Zeichenfolge "0", "01", "012", "0123", ... , "0123456789" untereinander ausgibt. Die Anführungszeichen gehören nicht zur Ausgabe.<br>Hinweis: Verwenden Sie die Lösung aus der vorhergehenden Aufgabe und ändern Sie das Programm so ab, dass der Zähler nicht als Zahl, sondern als Zeichen interpretiert und ausgegeben wird.
# Benutzen Sie die Lösung von Übungsaufgabe 1 und schreiben Sie das Programm so um, dass an Stelle der for-Schleife eine while-Schleife zum Einsatz kommt.<br>Hinweis: Ersetzen Sie die for-Schleife durch eine while-Schleife, definieren Sie vor der Schleife die Zählvariable und erhöhen Sie diese im Schleifenrumpf durch Addition von 1.
# Schreiben Sie eine HTML-Seite, die den Besucher der Seite beim Laden nach seinem Vornamen fragt und in Erfahrung bringt, ob er mit "Du" oder "Sie" angesprochen werden möchte. Anschließend erscheint ein kurzer Begrüßungstext, der den Namen des Besuchers hervorgehoben (fett) enthält und ihn korrekt mit "Du" oder "Sie" anredet. Zur Hervorhebung des Namens schreiben Sie bitte eine Funktion, die einen beliebigen Text, der als Parameter übergeben wird, in den <tt>strong</tt> HTML-Tag einschließt.<br>Hinweis: Zur Abfrage der Besucherinformationen dienen die Funktionen <tt>prompt()</tt> und <tt>confirm()</tt>. Die abgefragten Informationen können als Werte von globalen Variablen gespeichert werden, damit sie überall im Programm zur Verfügung stehen. Die Funktion zur Hervorhebung muss lediglich einen String als Parameter annehmen und als Ergebnis diese Zeichenkette, ergänzt <tt>strong</tt>, mit return als Ergebnis liefern. Das Hauptprogramm erzeugt mit <tt>document.writeln()</tt> die Ausgabe, wobei an geeigneter Stelle der Name, durch den Funktionsaufruf hervorgehoben, ausgegeben werden muss. Zur Anrede mit "Du" oder "Sie" macht eine if-then-else-Anweisung eine Fallunterscheidung, die auf die o.g. globale Variable Bezug nimmt.
# Schreiben Sie ein Programm, das ein assoziatives Array namens <tt>adresse[]</tt> definiert, dieses für die Indizes name, anschrift, plz, ort mit Werten füllt und die Werte anschließend in einer HTML-Tabelle darstellt.
# Arbeiten Sie den [http://javascript-workshop.de/buch/04.html online-Text] durch und lösen Sie eine selbstbestimmte Auswahl der angegebenen Übungsaufgaben.