Beruflich Dokumente
Kultur Dokumente
Fernuniversitat Hagen
ii
Inhaltsverzeichnis
1 Einleitung
2 Prototypenbasierte Programmierung
2.1 Historische Einordnung . . . . . . . . . . . . . . . . . . .
2.2 Prototypen in der objektorientierten Programmierung . .
2.3 Eigenschaften protoypenbasierter Programmiersprachen .
2.3.1 Fehlen von Klassen und Konstruktoren . . . . . .
2.3.2 Slots und Parent-Slot . . . . . . . . . . . . . . . .
2.3.3 Delegation . . . . . . . . . . . . . . . . . . . . . .
2.3.4 Vielfalt prototypenbasierter Programmiersprachen
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
2
3
3
3
4
5
3 Prototypen in JavaScript
3.1 Geschichte JavaScripts . . . . . . . . . . . . .
3.1.1 ECMAScript . . . . . . . . . . . . . .
3.1.2 JavaScript als missverstandene Sprache
3.1.3 JavaScript heute . . . . . . . . . . . .
3.2 Objekte in JavaScript . . . . . . . . . . . . . .
3.2.1 Objektliterale . . . . . . . . . . . . . .
3.2.2 Konstruktoren . . . . . . . . . . . . . .
3.2.3 Klonung und Erweiterung . . . . . . .
3.3 Prototype-Eigenschaft . . . . . . . . . . . . .
3.3.1 Object.prototype . . . . . . . . . . . .
3.3.2 [[Prototype]] und Konstruktoren . . . .
3.4 Delegation in JavaScript . . . . . . . . . . . .
3.5 Vererbung in JavaScript . . . . . . . . . . . .
3.5.1 Pseudo-klassenbasierte Vererbung . . .
3.5.2 Prototypenbasierte Vererbung . . . . .
3.5.3 Mischformen . . . . . . . . . . . . . . .
3.5.4 Mixins als Alternative . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
6
6
7
7
7
8
8
10
10
10
11
11
13
14
15
17
18
.
.
.
.
.
.
18
19
22
22
24
24
25
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5 Zuk
unftige Entwicklung und Fazit
26
6 Anhang
27
1 Einleitung
Diese Seminararbeit entstand im Rahmen des Kurses 1908 - OOP-Sprachen und
Konzepte an der Fernuniversitat Hagen, und beschaftigt sich mit der prototypenbasierten Programmiersprache JavaScript. Nach einer kurzen theoretischen Betrachtung
des Prototypenbegris und der prototypenbasierten Programmierung im Allgemeinen,
befasst sich der Hauptteil der Arbeit in den Kapiteln 3 und 4 mit einer konkreten
Implementierung einer solchen Sprache in Form von JavaScript und ihrem praktischen
Einsatz in Form der jQuery Bibliothek.
2 Prototypenbasierte Programmierung
Bevor das Themengebiet der prototypenbasierten Programmierung genauer untersucht
wird, soll zunachst die Entstehung des Begris Prototyp vorgestellt werden. Inter
essierte Leser finden hierzu in [1] eine ausf
uhrliche Ausarbeitung, die im nachsten Abschnitt kurz zusammengefasst wird.
Dieser Slot beihnaltet eine Referenz auf den Prototypen des Objektes, also das Objekt,
das beim Klonen also Vorlage diente. Der Parent-Slot spielt eine entscheidende Rolle
wiederum nach seinem Namen gefragt, muss die Anfrage nicht weitergeleitet werden,
da er selbst u
ussel verf
ugt.
ber einen Slot mit entsprechendem Schl
3
Mit Hilfe von statischen Variablen kann in den meisten klassenbasierten Sprachen auch ein gemeinsamer Zustand erzeugt werden.
In der klassenbasierten Programmierung werden die Begrie Delegation und Forwarding haufig
synonym verwendet. Gemeint ist meist Letzeres, siehe [12, S. 116 f.].
Kombination mit klassischer Vererbung. Objekte konnen in einem Objektbrowser erzeugt und von bereits existierenden Objekten abgeleitet werden. Prototypen
dienen in Omega daher zusatzlich der Definition von Interfaces, da abgeleitete
Objekte sicherstellen m
ussen, dass das Interface des Prototypen eingehalten wird
[13, 7, S. 104].
3 Prototypen in JavaScript
In diesem Kapitel wird die konkrete Implementierung einer prototypenbasierten Programmiersprache anhand der weit verbreiteten Sprache JavaScript vorgestellt. Im ersten Teil wird die Geschichte JavaScripts kurz vorgestellt. Nach einem kurzen Exkurs
zum Objektbegri beschaftigt sich der Hauptteil dieses Kapitels mit dem Konzept des
Prototypen, sowie der Delegation und Vererbung.
3.1.1 ECMAScript
Die alternativen Implementierungen der Sprache f
uhrten zum sog. Browserkrieg und
der damit verbundenen Problematik der konkurrierenden DHTML-Implementierungen.
Da jeder Browser u
ugte, mussten Entwickler
ber eigene Features und Interfaces verf
haufig browser-spezifischen Quelltext schreiben. Um den Inkompatibilitaten und der
resultierenden Doppelbelastung entgegenzuwirken, meldete der Microsoft Konzern bereits 1996 eine Spezifikation der Sprache beim European Computer Manufacturers
Association (ECMA) an. Rechtsstreitigkeiten f
uhrten dazu, dass der verabschiedete
Standard weder Java- noch J-, sondern ECMAScript6 hie [15, S. 2].
Die relevanten Versionen von ECMAScript sind die Versionen 3 und 5, die 1999 und
2009 verabschiedet wurden, und die Sprache um wichtige Features wie z.B. Regular
Expressions und den Strict mode erweitert haben [16].
In diesem Dokument wird der Begri JavaScript synonym zur Implementierung der
ECMAScript Version 5.1 verwendet. Sollte eine andere Version des Standards gemeint
sein, so wird an der jeweiligen Stelle explizit darauf hingewiesen.
5
6
an der Verbesserung von JavaScripts Ruf beteiligt war, bezeichnet unter [17] JavaScript
als die am meisten missverstandenste Programmiersprache. Am meisten bezeichnet
dabei nicht nur die Anzahl der Missverstandnisse selbst, sondern auch die groe Menge
an Entwicklern, die die Sprache missverstehen. Letzeres liegt vor allem an der groen
Verbreitung der Sprache, die von vielen modernen Browsern interpretiert werden kann.
Die beiden wichtigsten Missverstandnisse lauten:
Namensgebung: Der Name der Programmiersprache lasst auf eine Verwandtschaft mit der objektorientierten und vor allem klassenbasierten Sprache Java schlieen. Leider haben die beiden Sprachen auer der C-ahnlichen Syntax
keine Gemeinsamkeiten. Die Bezeichnung JavaScript ist ein reiner MarketingSchachzug gewesen, der die Sprache popularer machen sollte [14]. Die Tatsache,
dass der Sprachstandard ECMAScript heit und es diverse Implementierungen
gibt (JavaScript, ActionScript, JScript) tat ihr Restliches, um zur allgemeinen
Verwirrung beizutragen.
Unbekannte Konzepte: Das Konzept der funktionalen Programmierung ist
vielen Entwicklern einfach nicht vertraut. Hinzu kommt, dass die Prinzipien der
objektorientierten Programmierung zwar durchaus bekannt sind, aber die meisten Sprachen doch auf klassenbasierte Implementierungen setzen. Es ist also nicht
verwunderlich, wenn viele Entwickler schon fast krampfhaft versuchen JavaScript
die Idee der Klassen aufzudr
ucken. Die irref
uhrende Terminologie des sog. Konstruktors (siehe Abschnitt 3.2.2) ist nicht minder unbeteiligt am Durcheinander
[18, S. 90-94].
3.1.3 JavaScript heute
Heute stellt der Browser weiterhin die Hauptdomane JavaScripts dar, dabei wird die
Sprache durch viele Bibliotheken erganzt, die dem Webdesigner bei seiner taglichen Arbeit behilflich sind, und die Dierenzen der verschiedenen Browser-Implementierungen
nivellieren. Mit jQuery wird in Kaptitel 4 eine solche Bibliothek vorgestellt.
Im Jahr 2009 hat JavaScript den Sprung aus dem Browser hinaus geschat und kann
seit dem universell d.h. auf Client- und Serverseite verwendet werden. Mit node.js schuf
der Entwickler Ryan Dahl ein Framework, das sich durch hohe Performanz auerhalb
des Browsers auszeichnet.
Mit ECMAScript Version 6 befindet sich die nachste Novelle des Sprachstandards bereits in der Entwicklung.7
orientiert sich dabei an dem bereits beschrieben Konzept der Slots, die in JavaScript
Properties und im weiteren Verlauf der Arbeit einfach Eigenschaften oder Attribute
genannt werden. Ein solches Attribut besteht dabei aus einem Schl
ussel-Wert-Paar,
wobei der Schl
ussel stets vom Typ String sein muss, wahrend der Wert einen beliebigen Datentypen annehmen kann [19, S. 48, 15, S. 115].
Da JavaScript frei von Klassen ist, m
ussen Objekte auf andere Arten erstellt werden
konnen, dabei unterscheidet die Sprache insgesamt vier unterschiedliche Arten der Objekterzeugung, die in den nachsten Unterkapiteln vorgestellt werden sollen.
3.2.1 Objektliterale
Die einfachste Form der Erstellung von Objekten ist ex nihilo in Form sog. Objektliterale, die eine Erzeugung an Ort und Stelle ermoglichen. Auf diese Art und Weise
konnen Zustand und Verhalten eines Objektes vollstandig definiert werden [20, S. 21].
Die dabei verwendete Notation nennt sich JavaScript Object Notation (JSON ), und
wird im Bereich der Webtechnologie haufig zur Serialisierung von Daten verwendet
[21].
Listing 1: Objekterzeugung mittels Objektliteral
1
2
3
4
5
6
7
8
9
10
11
var clyde = {
name : " Clyde " ,
numberOfTusks : 2 ,
makeNoise : function () {
console.log ( " Tooeroooe ! " ) ;
}
}
console.log ( clyde.name ) ; // " Clyde "
console.log ( clyde [ " numberOfTusks " ]) ; // 2
clyde.makeNoise () ; // " Tooeroooe !"
In Listing 1 wird ein Objekt namens Clyde erstellt, das neben den beiden Eigen
schaften name und numberOfTusks u
ugt. Die Zeilen
ber die Funktion8 makeNoise verf
9 und 10 des Beispiels zeigen die beiden Arten des Zugris auf die Eigenschaften eines Objektes. Dabei ist der Zugri mittels sog. Dot-Notation (Zeile 9) aquivalent zum
Zugri u
ussel (Zeile 10), wobei sich Letzterer besonders gut f
ur reflektive
ber den Schl
Aufrufe eignet.
3.2.2 Konstruktoren
Neben den Objektliteralen ist eine Objekterzeugung mittels sog. Konstruktoraufruf
moglich. Konstruktoren sind gewohnliche Funktionen, deren Name per Konvention
gro geschrieben wird. Eine Funktion wird allerdings erst als Konstruktor verwendet,
wenn sie mit dem Schl
usselwort new aufgerufen wird.
8
Man k
onnte genau so gut von einer Methode sprechen. Da in JavaScript jede Funktion zu einem
Objekt geh
ort (im Zweifelsfall zum sog. globalen Objekt) ist jede Funktion gleichzeitig auch eine Methode. Um den funktionalen Charakter der Sprache zu unterstreichen, verwende ich den
Ausdruck Funktion.
Analog zum vorherigem Beispiel wird in Listing 1 ein Objekt namens Clyde erzugt,
10
3.3 Prototype-Eigenschaft
Im vorherigen Kapitel wurde bereits mehrfach die sog. Prototyp-Eigenschaft eines
Objektes angesprochen. Diese spezielle Eigenschaft referenziert ein weiteres Objekt,
namlich seinen sog. Prototypen. In JavaScript entsprechen Prototypen dem bereits
vorgestellte Konzept des Parent-Slots, das bereits am Beispiel von Self erlautert wurde. Die Bedeutung des Begris Prototyp ist in JavaScript allerdings mehrfach belegt
und soll an dieser Stelle genauer betrachtet werden [23, S. 83, 24].
Prototyp als Referenz auf das Elternobjekt: Der Begri Prototyp kann
zum einen, wie bereits erlautert, eine Referenz auf das Elternobjekt bezeichnen.
Es handelt sich dabei um eine spezielle Eigenschaft eines Objektes, die durch den
ECMAScript Standard spezifiziert wird. Diese Eigenschaft wird anlehnend an die
Notation des Standards auch haufig als [[Prototype]] bezeichnet.
In ECMAScript 5.1 und fr
uher bezeichnete [[Prototype]] eine interne Eigenschaft eines Objekts, f
ur die keine Zugrismethoden existierten. Einige Browserhersteller setzen sich in der Vergangenheit u
ber den Standard hinweg und
ermoglichten den Zugri auf das Elternobjekt u
ber die proprietare Eigenschaft
proto . Diese Idee wurde im vorlaufigen ECMAScript 6 Standard aufgegriffen und in Form der Eigenschaft Object.prototype. proto u
bernommen [25,
Kap. B.2.2.1].
Prototyp als Konstruktoreigenschaft: Funktionen verf
ugen u
ber eine zusatzliche Eigenschaft namens prototype, auf die explizit zugegrien werden kann.
Diese Eigenschaft spielt eine wichtige Rolle bei der Objekterzeugung, falls die
Funktion als Konstruktur verwendet wird. [[Prototype]] und prototype bezeichnen im Fall von Funktionen also zwei verschiedene Eigenschaften.
3.3.1 Object.prototype
Wird ein Objekt mittels Objektliteral oder new Object() erzeugt, so verweist [[Prototype]] auf einen besonderen Prototypen, namlich Object.prototype. Object.prototype ist ein besonderes Objekt, das von der entsprechenden Laufzeitumgebung bereitgestellt wird, und eine Menge von Standardfunktionen (z.B. toString() und isPrototypeOf()) bereitstellt. Object.prototype ist insofern besonders, da es selbst
u
ugt [26].
ber keinen eigenen Prototypen verf
Listing 4: Object.prototype als besonderer Prototyp
1
2
o = {}
Obj e c t . g e t P r o t o t y p e O f ( o ) === Obje ct.pro totyp e; // true
11
Listing 5: Anderungen
an Prototyp-Objekten
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Es wurde bereits mehrfach erwahnt, dass Konstruktoren in JavaScript einfache Funktionen sind. Da Funktionen selbst first-class citizens, also Objekte sind, verf
ugen
In Wirklichkeit handelt es sich bei dieser Grafik, die so oder so in ahnlich in vielen Lehrb
uchern
und auf vielen Webseiten gefunden werden kann um eine Vereinfachung des Sachverhalts. An dem
simplen Aufruf Elephant() sind in Wirklichkeit mehr Objekte beteiligt, da die Funktion selbst
auch u
ugt. F
ur Details siehe [27].
ber die Eigenschaft [[Prototype]] verf
12
Wir wollen anhand des Listings 6 das Prinzip der Delegation in JavaScript noch einmal
nachvollziehen. Nach der Definition des Konstruktors und der Erweiterung des Proto-
13
Prototypen verf
ugen.
Wir wollen nun den umgekehrten Fall betrachten und eine Eigenschaft eines bereits
erzeugten Elefanten modifizieren. In Zeile 19 verliert Fred einen Stozahn. In den bei
den folgenden Zeilen sieht man, dass die Zuweisung nur Auswirkungen auf das Objekt
fred hat. Dies erklart sich dadurch, dass die Zuweisung die Erzeugung einer neuen
Eigenschaft im Objekt selbst zur Folge hat, und nicht an den Prototypen delegiert
wird. Das Objekt fred verf
ugt nun also u
ur die Eigenschaft
ber einen eigenen Wert f
numberOfTusks, was zur Folge hat, dass der Mechanismus des Prototype-Chaining bereits vorzeitig f
undig wird, und die Anfrage nicht an [[Prototype]] delegiert werden
muss. Man nennt dieses Verhalten Shadowing und es bietet den Vorteil, dass lokale
Anderungen
an einem Kind eines Prototypen nicht ungewollt alle anderen Kinder des
gleichen Prototypen modifizieren.
Abbildung 5 stellt die beiden Objekte und die Beziehung zu ihren Prototypen noch
einmal grafisch dar.
14
Es ist allerdings leicht zu erkennen, dass sich mit dem Ansatz der Delegation eine
mehrstufige Anordnung von verschiedenen Objekt erzielen lasst, mit der die klassenbasierte Vererbung (implementation inheritance) simuliert werden kann. In der Literatur
werden dabei verschiedene Ansatze diskutiert, die an dieser Stelle vorgestellt werden
sollen.
3.5.1 Pseudo-klassenbasierte Vererbung
Anhand von Listing 7 wollen wird die sog. pseudo-klassenbasierte Vererbung betrachten.
Listing 7: Pseudo-klassenbasierte Vererbung
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Diese Form der Vererbung in JavaScript orientiert sich stark an der klassenbasierten
Vererbung. Es werden zwei Konstruktoren definiert, deren Prototypen u
ber zusatzliche
Eigenschaften verf
ugen. Die tatsachliche Implementierung der Vererbung findet in Zei
le 14 des Listings 7 statt. Durch das Uberschreiben
der Prototyp-Eigenschaft des
Konstruktors wird ein neues Objekt (ein Saugetier) erzeugt, dessen interne [[Prototype]]-Eigenschaft auf Mammal.prototype verweist. Das entstandene Objektgeflecht
ist in Abbildung 6 dargestellt. Dieser haufig verwendete Ansatz wird gerne um weiteren
Funktionalitaten, wie z.B abstrakten Klassen, erweitert (siehe z.B. [15, Kap. 9.7.4].
Es gibt allerdings auch Kritik an dieser Art der Realisierung von Vererbung, die im
Wesentlichen mit der Verwendung von Konstruktoraufrufen zusammenhangt. Neben
der bereits bekannten Kritik an der Mechanik des Konstruktoraufrufs in JavaScript,
ist diese Variante im Entwurf unvorteilhaft. Zum einen wird durch den Aufruf new
Mammal() in Zeile 14 ein konkretes Saugetier erzeugt, obwohl man ja eigentlich nur
einen Prototypen benotigt.10 Es findet also konzeptionell eine Vermischung zwischen
10
15
Der Konstruktor des Saugetiers wird in Listing 7 lediglich einmal zur Erzeugung des
Prototypenobjektes ausgef
uhrt. Da zum Zeitpunkt des Aufrufs auch keine sinnvollen Daten zur Verf
ugung stehen, werden auch keine Argumente an den Konstruktor
u
uhren, wenn
bergeben. Dies kann zusatzlich zu unvorhergesehenen Komplikationen f
der Konstruktor sinnvolle Werte f
ur seine korrekte Ausf
uhrung benotigt [20, S. 48, 18,
S. 102].
3.5.2 Prototypenbasierte Vererbung
Bis zur Freigabe des ECMAScript Standards in der Version 5.1 war die im vorherigen Abschnitt vorgestellte Methode die bevorzugte Art und Weise Vererbung in JavaScript zu simulieren. Mit der genannten Version des Standards wurde die Funktion
Object.create() eingef
uhrt, die einen nat
urlicheren Weg zur Realisierung von Vererbung ermoglicht. Die Funktion ermoglicht eine Vererbung unter Objekten, unabhangig
von Klassenobjekten und Konstruktoren, durch Klonung und Erweiterung existierender
Objekte. Sie wird wahlweise mit einem oder mit zwei Argumenten aufgerufen, wobei
das erste Argument stets das bereits vorhandene Objekt erwartet, das der [[Prototype]]-Eigenschaft eines neu erzeugten Objektes zugewiesen werden soll [18, S. 109
f.]. Die Funktionsweise soll an Listing 8 nachvollzogen werden.
Listing 8: Object.create Polyfill
1
2
11
In Abschnitt 3.5.3 wird gezeigt, wie man zumindest diese Unschonheit beseitigen kann.
16
function F () {}
F.prototype = o;
return new F () ;
};
}
newObject = Object.create ( oldObject ) ;
Die standardisierte Implementierung der Funktion bietet zusatzlich die Moglichkeit eine Menge von Eigenschaften, in Form eines weiteren Parameters, zu u
bergeben, um
die das neue Objekt erweitert wird.
Listing 9: Klonung und Erweiterung von Objekten
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Im Listing 9 wird Object.create() verwendet, um eine mehrstufige Beziehung zwischen Objekten zu realisieren. Die Zeile 4 zeigt die Verwendung der Funktion zur
12
17
Klonung eines existierenden Objektes. In den Zeile 10-23 erfolgt eine Erweiterung, des
zuvor erstellen Klons, um die Eigenschaft isMatriarch. Die Erlauterung der Notation
zur Erweiterung eines Objektes (configurable, enumerable usw.) w
urde an dieser
Stelle den Rahmen der Arbeit sprengen. Es ist lediglich darauf hinzuweisen, dass die
Eigenschaft value den tatsachlichen Wert, den die neu hinzugef
ugte Eigenschaft erhalten soll, enthalt. Zusatzlich wird der Wert des bereits vorhandenen Attributs name
in den Zeilen 17-21 u
berschrieben.
Diese Form der Vererbung wird auch haufig dierentielle Vererbung genannt und erlaubt in JavaScript sogar das Entfernen vorhandener Attribute. Das resultierende Objektgeflecht wird in Abbildung 7 gezeigt.
3.5.3 Mischformen
In der j
ungeren Literatur zu JavaScript finden sich zunehmend Mischformen aus den
beiden vorgestellten Vererbungsmechanismen. So konnen beispielsweise die Nachteile der pseudo-klassenbasierten Vererbung durch den Quelltext aus Listing 10 abgeschwacht werden [28, 19, S. 69-72, 18, S. 100-103].
Listing 10: Prototypenbasierte Vererbung
1
2
3
4
5
6
7
8
9
10
11
12
13
14
18
Das Schl
usselwort in in der zweiten Zeile von Listing 11 ermoglicht den iterativen
Zugri auf alle Eigenschaften eines Objektes. Mit hasOwnProperty() kann gepr
uft
werden, ob die Eigenschaft eines Objektes von diesem Objekt selbst stammt oder mittels Delegation von einem Prototypen abgeleitet wurde. Handelt es sich um eine eigene
Eigenschaft, so wird diese an den Empfanger (receiver) weitergegeben. Nach Beenden der Schleife verf
ugt der Empfanger u
ber alle Eigenschaften des Vorlage-Objektes
(supplier). Mit dieser Methode ware es moglich mehrere Objekte miteinander zu vermischen und so eine Art von Mehrfachvererbung zu implementieren, wobei allerdings
schnell klar werden sollte, dass man spatestens bei Eigenschaften mit gleichem Namen
vor einem Problem st
unde.
19
der Praxis. Der Schwerpunkt liegt hierbei auf der Untersuchung der weit verbreiteten
Bibliothek jQuery. Nach einer kurzen Vorstellung der Software und ihres Funktionsumfangs, erfolgt im letzten Teil des Kapitels eine genauere Betrachtung von relevanten
Quelltextausschnitten.
// jQuery
$.post ( ' www.example.com / login ' , { username: ' fred ' } , function (
data ) {
// Verarbeitung
})
// JavaScript
Dieser Kern heit heute Sizzle.js und wird als selbststandiges Projekt unter http://sizzlejs.com/
weitergepflegt.
20
Listing 12 zeigt einen asynchronen Serveraufruf mittels der POST-Methode des HTTPProtokolls. Die Zeilen 2-4 zeigen die Implementierung mittels jQuery, die u
brigen Zeilen
die klassische Variante mit JavaScript. Der reduzierte Aufwand f
ur den Programmierer
wird durch den Umfang der beiden Beispiele deutlich.
JQuery hat sich im Laufe der Jahre zu einem De-facto-Standard entwickelt. Viele
Quelltext-Ausschnitte in Fachb
uchern und auf Internetportalen nutzen die jQueryNotation ohne explizit darauf hinzuweisen. Deutlich wird die hohe Verbreitung, wenn
man sich in Abbildung 8 die Nutzung und Marktanteile der Bibliothek im Vergleich zur
Konkurrenz anschaut. Von den beobachteten Internetseiten, die http://www.w3techs.
com in regelmaigen Abstanden untersucht, nutzen 35,1% u
berhaupt keine Bibliotheken. 61,3% der beobachteten Seiten nutzen jQuery, was einem Marktanteil von 93,4%
entspricht.14
Die Webseite http://www.builtwith.com benennt f
ur den November 2014 49,4 Mio.
Internetauftritte, die Verwendung von der Software machen. Abgeschlagen auf dem
zweiten Platz befindet sich der Konkurrent MooTools mit 3,6 Mio. Installationen. Diesen starken Erfolg verdankt jQuery nicht nur der Selektor-Mechanik, sondern auch
einer Menge von weiteren Funktionen, um die das Projekt im Laufe der Jahre erweitert wurde [32, 33]. Die wichtigsten Funktionen lauten:
DOM-Manipulation: Der wichtigste Einsatzzweck ist die bereits beschriebene Veranderung des Document Object Model innerhalb eines Webbrowsers. Bereits existierende DOM-Elemente konnen mittels CSS-Selektoren ausgewahlt und
verandert werden. Neue Elemente konnen bequem erzeugt und in die existierende
Hierarchie eingef
ugt werden.
Ereignisbehandlung: Als clientseitige Technologie nutzt JavaScript ausgiebig
Techniken der Ereignisbehandlung. Die jQuery-Bibliothek unterst
utzt den Entwickler mit einer Vielzahl von browserunabhangigen Ereignisfunktionen, die auf
DOM-Elemente angewendet werden konnen. Dabei bietet jQuery sogar die Moglichkeit auf Ereignisse zuk
unftiger Elemente, also Teilen des Dokuments, die nachtraglich dynamisch hinzugef
ugt wurden, zu reagieren.
Es ist zu beachten, dass Webseiten auch haufig mehrere Bibliotheken gleichzeitig nutzen.
Das Projekt jQueryUI auf http://jqueryui.com/ erweitert diese Funktionalitat noch einmal deutlich.
21
gezeigte Quelltextbeispiel (Listing 12) sollte vermittelt haben, dass jQuery dies
durchaus gelingt.
Erh
ohte Lesbarkeit: Die Tatsache, dass durch geschickte Nutzung von Ereignismethoden samtlicher Quelltext in JavaScript vom eigentlichen XML/HTML
getrennt werden kann (sog. unobtrusive JavaScript), erhoht zusammen mit den
kurzen Quelltexten die Lesbarkeit.
22
Browserkompatibilit
at: Die Gewahrleistung der Browserkompatibilitat wurde nun bereits mehrfach erwahnt. JQuery unterst
utzt sieben gangige Browser,
darunter zwei mobile Anwendungen.
Einfach zu erlernen: Durch die einfache Syntax, die Verwendung von CSSSelektoren und gut dokumentierten Funktionen, die mit wenig Aufwand viele
Anderungen
gleichzeitig am DOM zulassen, ist jQuery leicht zu erlernen.
Groe Community: Mit der bereits besprochenen hohen Verbreitung geht auch
eine sehr groe Entwicklergemeinschaft einher.
Kostenlos: Die Bibliothek ist kostenlos und kann auf der Projektwebseite heruntergeladen werden oder u
ber ein sog. Content Delivery Network (CDN) in das
eigene Projekt integriert werden.
Erweiterbarkeit: JQuery bietet Erweiterungsmoglichkeiten, mit denen das Projekt um zusatzliche Funktionen erganzt werden kann. Wie die Erweiterung der
Bibliothek technisch realisiert wird, ist unter anderem Inhalt des nachsten Abschnitts.
Demgegen
uber steht eine geringe Anzahl von Nachteilen:
Dateigr
oe: Die Bibliothek ist durch den hohen Funktionsumfang mit einer
Dateigroe von 86 KByte sehr gro. Dies kann vor allem im mobilen Bereich zu
langen Ladezeiten f
uhren.
Verdr
angung von JavaScript: Die hohe Verbreitung jQueries hat zur Folge,
dass viele Entwickler kaum Kontakt mit den standardisierten Browser-APIs haben und f
ur viele Einsatzfalle nur noch die Bibliotheksfunktionen nutzen. Prinzipiell spricht nichts gegen ein solche Nutzung, solange der Entwickler u
ber Kenntnisse der dahinter liegenden Sprache verf
ugt und nicht blind auf fremde Implementierungen vertraut.
23
Es handelt sich bei dem Konstrukt in Listing 13 um eine sog. Immediately Invoked
Function Expression(IIFE), also um die Definition einer anonymen Funktion, die direkt
ausgef
uhrt wird. Die Bibliothek stellt so sicher, dass sie an der Stelle, an der sie in ein
Projekt eingebunden wird, auch ausgef
uhrt wird. Die Parameter der Funktion sind
zum einen das globale Objekt, das durch die Laufzeitumgebung bereitgestellt wird,
und zum anderen eine anonyme Funktion, die f
ur die eigentliche Initialisierung des
Objektes zustandig ist und vom Funktionsparameter als factory bezeichnet wird.
Die Erzeugung eines jQuery-Objektes ist sehr simpel und wird in Listing 14 gezeigt.
Listing 14: Erzeugung eines jQuery-Objektes
1
$("a")
In Listing 14 wird ein Objekt erzeugt, das alle Elemente des Typs a, also alle(!) Ankerpunkte innerhalb des Dokumentes referenziert. Es fallt auf, dass f
ur die Objekterzeugung weder das Schl
usselwort new noch eine explizite Benennung eines Prototypen
genutzt wird.
Listing 15: Initialisierung des jQuery-Objektes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Dies wird erreicht, indem die Funktion jQuery selbst den Konstruktoraufruf tatigt und
eine Funktion namens init auf dem Objekt jQuery.fn aufruft (Listing 15, Zeile 5).
Die Funktion init konfiguriert, abhangig von den u
bergebenen Parametern, das neu
erzeugte Objekt und ist somit die wahre Konstruktorfunktion der Bibliothek. Dies erklart auch die Zuweisung in der letzten Zeile des Listings 15. Da es sich bei init um den
eigentlichen Konstruktor handelt, muss dieser Funktion auch der Prototyp zugewiesen
werden, mit dem die spatere [[Prototype]]-Eigenschaft des neuen jQuery-Objektes
belegt werden soll.
24
before: function () {
return this.domManip ( arguments , function ( elem ) {
if ( this.parentNode ) {
t h i s . p a r e n t N o d e . i n s e r t B e f o r e ( elem , this ) ;
}
}) ;
},
Innerhalb der Funktion des Prototypen sieht man die Verwendung von this.parentNode,
wobei this in diesem Fall den Aufrufer, also ein konkretes jQuery-Objekt, und nicht
jQuery.fn selbst meint.
4.2.3 Weitere Besonderheiten im Entwurf
Bei naherer Betrachtung des Quelltextes fallen weitere Entwurfsentscheidungen auf,
die teilweise ausgiebig Gebrauch von JavaScripts Sprachfeatures machen, und durch
geschickte Implementierungen die Nutzung der Bibliothek deutlich vereinfachen.
Globale Referenz: Das jQuery-Objekt wird nach Initialisierung als globale Referenz gespeichert. Dies hat den Vorteil, dass standig eine Referenz auf den Prototypen jQuery.fn existent und somit unerreichbar f
ur die Garbage Collection
bleibt. Zum anderen fiel die Wahl des globalen Variablennamens auf ein einfaches Dollarzeichen ($)17 , das zu der mehrfach vorgestellten und pragnanten
Kurzschreibweise zur Erzeugung von jQuery-Objekten f
uhrt.
17
Siehe [36] f
ur g
ultige Identifizierer in JavaScript.
25
<html >
<head >
<script src= " https: // code.jquery.com / jquery-2.1.1.js " type= "
text / javascript " > </script >
<script type= " text / javascript " >
$ ( function () {
$ ( " li " ) . click ( function () {
$ ( this ) . css ( ' color ' , ' red ') . fadeOut ( ' slow ') ;
}) ;
}) ;
</script >
</head >
<body >
<ul >
<li > Clyde </li >
<li > Fred </li >
<li > Bonny </li >
</ul >
</body >
</html >
Listing 17 zeigt eine HTML-Seite mit einer ungeordneten Liste, die drei Eintrage
enthalt. Der JavaScript-Quelltext startet in Zeile 5 mit dem sog. Document-ReadyEvent, einer Callback-Funktion, die ausgelost wird, sobald der Browser das DOM
vollstandig geladen hat.
In Zeile 6 wird zunachst nun ein neues jQuery-Objekt mit dem Selektor li, also ein
26
dieser Elemente wird nun ein neuer Event-Listener zugewiesen, wobei die Zuweisung
implizit f
ur alle Elemente erfolgt (Zeile 6). Wird ein Element vom Benutzer angeklickt,
so wird die u
bergebene Callback-Funktion aufgerufen, die bewirkt, dass die Farbe des
Elements auf rot geandert, und das Element daraufhin langsam ausgeblendet wird
5 Zuku
nftige Entwicklung und Fazit
Douglas Crockford bezeichnet JavaScript als die missverstandenste Programmiersprache der Welt, denn vielen Entwicklern sind die funktionalen und prototypenbasierten
Spracheigenschaften unbekannt18 , was sicherlich an der eingeschrankten Nutzung zur
DOM-Manipulation im Browser und der klassenbasierten Herkunft der Programmie
rer liegt. Die Kapitel 3 und 4 dieser Arbeit sollten gezeigt haben, dass die Sprache mit
ihren Prototypen, dem machtigen Konzept der Delegation sowie Closures u
ber eine
Menge von flexiblen Werkzeugen verf
ugt, mit der sich weitaus mehr als die Modifikation von Webseiten erzielen lasst.
Mit der schlechten Namenswahl der Sprache, dem Konzept der Konstruktoren und der
unklaren Verwendung des Klassenbegris durch viele Autoren wurden im Verlauf der
Arbeit einige Makel JavaScripts in Bezug auf Prototypen aufgezeigt.
Ein Blick auf die neuesten Entwicklungen des Sprachstandards und aktuelle Praxisb
ucher (z.B. [18, 19, 20]) zeigt, dass der Verwendung von prototypenbasierter Programmierung in JavaScript in den letzten Jahren erhohte Aufmerksamkeit geboten
wurde. Standardisierte Funkionen wie Object.create oder Object.isPrototypeOf
brachten ernsthafte Alternativen zu den klassischen Entwurfsmustern JavaScripts, die
sich vorwiegend auf die Nachahmung der klassenbasierten Programmierung konzentrierten.
Die ECMAScript Version 6, die sich noch im Entwurfsstadium befindet19 , erweitert
sowohl die konstruktor- als auch die prototypenbasierten Merkmale der Sprache um
neue Funktionalitaten. Mit der Einf
uhrung des Schl
usselwortes class wird ein Wrapper f
ur die pseudoklassenbasierte Vererbung, wie sie in Kapitel 3.5.1 beschrieben wurde,
eingef
uhrt.20 Die direkte Belegung von [[Prototype]] innerhalb von Objektliteralen,
sowie die Moglichkeit, das Prototypenobjekt dynamisch zu andern, erhohen nochmals
die Flexibilitat der Sprache.
In Kapitel 4 wurde anhand praktischer Beispiele gezeigt, wie jQuery JavaScripts Spracheigenschaften einsetzt, um eine performante, robuste und leicht verwendbare Nutzung
seiner Bibliotheksfunktionen zu ermoglichen.
Die Vielseitigkeit der Sprache wird noch deutlicher, wenn man sich aus JavaScripts
18
27
Hauptdomane, dem Browser, entfernt, denn durch die flexible Paarung aus funktionaler und prototypenbasiert Entwicklung hat die Sprache ihren Weg in diverse andere Einsatzgebiete gefunden. Mit node.js21 existiert seit 2009 ein Framework, das die
serverseitige Implementierung von Webseiten mit JavaScript ermoglicht. Node.js bietet dabei den Vorteil client- und serverseitig die selbe Sprache zu nutzen, wobei der
Schwerpunkt auf der Verwendung des Ereignismodels (non-blocking I/O) JavaScripts
liegt. Auerhalb des WWW dient die Sprache hauptsachlich als Alternative zu existierenden Scriptsprachen und DSLs, so verwenden Applikationen wie beispielsweise der
Adobe Acrobat Reader, die dokumentenbasierte Datenbank MongoDB oder die SpielEngine Unity allesamt JavaScript als Scriptsprache, und tragen zur Verbreitung der
prototypenbasierten Programmierung bei.
6 Anhang
Abbildungsverzeichnis
1
2
3
4
5
6
7
8
4
5
5
12
13
15
17
21
Literatur
[1] Antero Taivalsaari. Classes vs. prototypes - Some Philosophical and Historical
Observations. In: Journal of Object-Oriented Programming (1996).
[2] Stanford Encyclopedia of Philosophy. Plato. 2013. url: http://stanford.io/
1pjfY82 (besucht am 18. 11. 2014).
[3] Stanford Encyclopedia of Philosophy. Aristotle. 2011. url: http://stanford.
io/11sN62m (besucht am 18. 11. 2014).
[4] Ludwig Wittgenstein. Philosophische Untersuchungen. Frankfurt am Main: Suhrkamp, 1971. isbn: 3-518-06514-9.
[5] George Lako. Women, fire, and dangerous things : what categories reveal about
the mind. Chicago: University of Chicago Press, 1987. isbn: 0-226-46804-6.
[6] Alan Borning. Classes versus Prototypes in Object-Oriented Languages. In:
Proceedings of the ACM/IEEE Fall Joint Computer Conference. November 1986.
1986, S. 3640. isbn: 0-8186-4743-4.
21
http://nodejs.org/
28
[7] G
unther Blaschek. Object-Oriented Programming with Prototypes. 1994. isbn:
978-3-642-78079-0.
[8] Henry Lieberman. Using Prototypical Objects to Implement Shared Behavior
in Object-Oriented Systems. In: OOPSLA86, ACM SIGPLAN. Bd. 21. 1. Nov.
1986.
[9] Christophe Dony, Jacques Malenfant und Daniel Bardou. Classifying Prototypebased Programming Languages. In: Prototype-Based Object-Oriented Programming: Concepts, Languages and Applications. Hrsg. von James Noble, Antero
Taivalsaari und Ivan Moore. Springer, Feb. 1999. Kap. 2, S. 1745.
[10] Randall B. Smith und David Ungar. Programming as an Experience: The Inspiration for Self. In: Proceedings ECOOP 95. Bd. 952. LNCS. Springer-Verlag,
Aug. 1995, S. 303330.
[11] Marvin L. Minsky. A Framework for Representing Knowledge. In: The Psychology of Computer Vision. New York: McGraw-Hill, 1975, S. 211277.
[12] F. Steimann. Moderne Programmiertechniken und -methoden: Kurseinheiten 1 7. FernUniversitat Hagen, 2012.
[13] G
unther Blaschek. The Omega Language - Introduction. url: http://bit.ly/
1voFkB4 (besucht am 28. 11. 2014).
[14] Charles Severance. JavaScript: Designing a Language in 10 Days. In: IEEE
Computer 45.2 (2012), S. 78.
[15] David Flanagan und Dan Shafer. JavaScript: The Definitive Guide. OReilly &
Associates, 1998, S. 776. isbn: 1-56592-392-8.
[16] ECMA. Standard ECMA 262, ECMAScript Language Specification. url: http:
//bit.ly/1vpiqe4 (besucht am 27. 11. 2014).
[17] Douglas Crockford. JavaScript: The Worlds Most Misunderstood Programming
Language. 2001. url: http://bit.ly/1vpivyk (besucht am 27. 11. 2014).
[18] Kyle Simpson. By Kyle Simpson You Dont Know JS: this & Object Prototypes.
OReilly Media, Aug. 2014.
[19] Nicholas C. Zakas. The Principles of Object-Oriented JavaScript. 1. Aufl. No
Starch Press, Feb. 2014. isbn: 978-1-593-27540-2.
[20] Douglas Crockford. JavaScript: The Good Parts. 1st. OReilly Media, Mai 2008.
isbn: 978-0-596-51774-8.
[21] ECMA. ECMA-404: The JSON Data Interchange Format. 1st. ECMA (European
Association for Standardizing Information und Communication Systems), Okt.
2013. url: http://bit.ly/1vRJ7u6 (besucht am 27. 11. 2014).
[22] Mozilla Developer Network (MDN) - new operator. 2014. url: http://mzl.la/
1xM2M9S (besucht am 27. 11. 2014).
[23] David Herman. Eective JavaScript: 68 Specific Ways to Harness the Power of
JavaScript. 1. Aufl. Addison-Wesley Professional, Dez. 2012. isbn: 978-0-32181218-6.
[24] Mozilla Developer Network (MDN) - Object.prototype. proto . 2014. url: http:
//mzl.la/1zSTq1S (besucht am 27. 11. 2014).
29