Sie sind auf Seite 1von 31

Seminararbeit im Kurs 1908

OOP-Sprachen und -Konzepte

Thema: Praxisorientierte Nutzung von


Prototypen in JavaScript am Beispiel
von jQuery
Autor: Robert Schweda
Matrikelnummer: 8802440

Fernuniversitat Hagen

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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

4 JavaScript in der Praxis


4.1 Das jQuery-Projekt . . . . . . . . . . . . . . .
4.2 Untersuchung ausgewahlter Quelltextpassagen
4.2.1 Initialisierung des jQuery-Objekts . . .
4.2.2 Verwendung von Prototypen . . . . . .
4.2.3 Weitere Besonderheiten im Entwurf . .
4.2.4 Praxisbeispiel . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

5 Zuk
unftige Entwicklung und Fazit

26

6 Anhang

27

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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.

2.1 Historische Einordnung


Die objektorientierte Programmierung ist eng mit dem Begri der Klasse verkn
upft.
Der Ursprung der Kategorisierung und des Klassenbegris selbst findet sich bereits in
der Antike bei Platon wieder. Platon unterscheidet zwischen zwei Arten von Objekten,
zum einen Objekte, die Eigenschaften von Dingen beschreiben (sog. Ideen, Formen)
und zum anderen real existierende Objekte, die diese Eigenschaften vereinen. Mit diesem Sachverhalt beschreibt der griechische Philosoph im Wesentlichen die Beziehung
zwischen Klassen und ihren Instanzen [2].
Sein Sch
uler Aristoteles formulierte mit der Definitionsregel genus proximum et dif
ferentia specifica die Prinzipien der Generalisierung und Spezialisierung, wie man sie
auch heute in der objektorientierten Programmierung wiederfindet. Nach Aristoteles
wird ein neuer Begri durch einen Oberbergri (genus proximum) und einer Menge
von Eigenschaften, die ihn von diesen abgrenzen, beschrieben (dierentia specifica) [3].
Kritik an dieser Form der Kategorisierung wurde im 20. Jahrhundert durch den Philosophen Ludwig Wittgenstein geauert. Wittgenstein stellte fest, dass es gewisse Dinge
gibt, die nicht klar kategorisiert werden konnen. Als Beispiel bringt er den allgemeinen
Begri des Spiels. Spiele verf
ugen u
ber eine Menge von Verwandtschaften, die Witt
genstein als Familienahnlichkeiten bezeichnet. Jedes individuelle Spiel verf
ugt u
ber
Eigenschaften, durch die es sich als Spiel auszeichnet, es existiert allerdings keine gemeinsame Eigenschaft, u
ugen [4, S. 56-68].
ber die alle Spiele verf
In den Siebzigerjahren setzte Elenoar Rosch die Forschung auf dem Gebiet der Familienahnlichkeiten fort. Sie stellte fest, dass es Entitaten gibt, die eine Klasse besser
reprasentieren als andere. Ein Singvogel ist beispielsweise ein typischerer Vertreter der
Kategorie Vogel als ein Pinguin oder ein Huhn. Diese klassenspezifischen Vertreter
bezeichnete sie als Prototypen [5].

Seminararbeit zum Kurs 1908 - Thema: JavaScript

2.2 Prototypen in der objektorientierten Programmierung


Wie Objekte in der realen Welt beschrieben werden, wirkt sich unmittelbar auf den Entwurf von Programmiersprachen aus, die mit diesen Objekten arbeiten m
ussen. Wie bei
der Kategorisierung anhand von Klassen in der Philosophie, existiert auch im Bereich
der klassenbasierten Programmierung Kritik an diesem Konzept. Die beiden wesentlichen Punkte dabei lauten nach [6] und [7, S. 92]:
Die Erstellung einer Klassenhierarchie ist ein kreativer Vorgang, der zu vielen
verschiedenen Losungen f
uhren kann. Dabei kann es sogar sein, dass eine Losung,
die sich in der Theorie als besonders elegant erweist, nicht praktikabel ist.
Der Begri der Klasse ist nicht eindeutig und reprasentiert unterschiedliche Konzepte. Klassen konnen mathematisch als Mengen interpretiert werden. Zugleich
dienen sie der Beschreibung ihrer Instanzen und bieten auerdem Mechanismen
zur Erzeugung dieser konkreten Vertreter.
In den achtziger Jahren befassten sich Wissenschaftler damit Alternativen zur klassenbasierten Programmierung zu erforschen und fokussierten sich dabei unter anderem
auf die Verwendung von Prototypen. Je nach Forschungsschwerpunkt variiert die Definition des Begris in den unterschiedlichen Veroentlichungen. Anlehnend an [7, S. 92]
wird in dieser Arbeit ein Prototyp als ein bereits vorgefertigtes, strukturiertes Objekt
mit Eigenschaften und einem Verhalten aufgefasst, das bei Bedarf als Vorlage f
ur die
Erstellung eines neuen Objektes herangezogen werden kann.
Ein anschauliches Beispiel f
ur diese Definition bietet Lieberman in [8]: Nehmen wir
an, wir kennen einen ganz bestimmten Elefanten namens Clyde (weil wir z.B. Tierpfleger im ortlichen Zoo sind), dann konnen wir unser Wissen u
ber Clyde dazu nutzen,
Aussagen u
ber einen anderen Elefanten, namentlich Fred, zu treen. Wir konnen beispielsweise sagen, dass Fred grau ist und vier Beine hat.1
Die Vorteile, die sich aus der Verwendung von Prototypen statt Klassen ergeben, lauten
nach [9]:
Es handelt sich um einen nat
urlicheren Ansatz, da man bei der Losung von
Problemen haufig versucht, von einem konkreten Fall ausgehend eine abstrakte
Losung zu finden. Die Nutzung von Prototypen spiegelt diese Vorgehensweise auf
der Ebene der Programmierung wider.

Eine flexiblere Nutzung von Objekten wird ermoglicht, da Anderungen


an einzelnen Objekten nicht alle anderen Instanzen dieses Typs betreen.
Klassen werden oft als komplex und einschrankend empfunden. Beispielsweise
werden in der Programmierung von grafischen Oberflachen haufig gleichartige
Elemente benotigt, die sich nur marginal (z.B. in der Eventverarbeitung) voneinander unterscheiden. Trotz der geringen Dierenzen m
usste f
ur jedes dieser
Elemente gleich eine neue Klasse definiert werden.

Die Tatsache, das Fred nicht grau ist oder u


urliche Anzahl an Beinen verf
ugen konnte,
ber eine unnat
ignorieren wir an dieser Stelle und verweisen auf die Abschnitte 2.3.3 und 3.4.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

2.3 Eigenschaften protoypenbasierter Programmiersprachen


Bevor im nachsten Kapitel mit JavaScript eine Implementierung einer prototypenbasierten Sprache untersucht wird, sollen in diesem der Teil Arbeit zunachst typische Eigenschaften einer solchen Sprache vorgestellt werden. Dabei ist zu beachten, dass nicht
jede Sprachimplementierung zwingend u
ugen muss.
ber alle vorgestellten Merkmale verf
Die erste prototypenbasierte Programmiersprache u
berhaupt war Self, die 1986 von
David Unger und Randall B. Smith entwickelt wurde, und die nachfolgend erlauterten
Spracheigenschaften allesamt implementierte [10].
2.3.1 Fehlen von Klassen und Konstruktoren
Charakteristisch f
ur die prototypenbasierte Programmierung ist das Fehlen von Klassen, das allerdings nicht automatisch den Wegfall aller klassenbasierter Konzepte, wie
z.B. der Vererbung, zur Folge hat. Durch den hohen Grad an Flexibilitat der prototypenbasierten Sprachen konnen diese Mechanismen haufig simuliert werden. In Abschnitt 3.5 werden beispielsweise gleich mehrere Varianten zur Realisierung von Vererbung in der Sprache JavaScript vorgestellt.
Mit dem Begri der Klasse fallt auch die Moglichkeit der Erzeugung von Instanzen
durch Konstruktoren weg. Es stellt sich nun die Frage, wie konkrete Objekte stattdessen erzeugt werden konnen? Hierzu benennt die Literatur verschiedene Moglichkeiten
[10, 7, S. 84 .]:
Klonung und Erweiterung existierender Objekte: Bei der Erzeugung eines
neuen Objektes durch Klonung wird ein bereits existierendes Objekt als Vorlage
f
ur ein neues Objekt herangezogen. Es wird neben dem Verhalten auch der Zustand des Ursprungsobjektes (parent) auf den Klon (child ) u
bertragen.
Eine Spezialform des Klonens stellt die Erweiterung dar. Sie ermoglicht es, ein
konkretes Objekt durch die Benennung eines Ursprungsobjektes und einer Menge
von weiteren Eigenschaften und Unterschieden zu erstellen.
Erzeugung ex nihilo: Bevor Objekte geklont oder erweitert werden konnen,
muss allerdings mindestens ein konkretes Objekt existieren. Dies kann bereits
durch die Laufzeitumgebung der Sprache bereitgestellt oder ex nihilo vom Programmierer erstellt werden. Unter Letzterem versteht man typischerweise eine
Beschreibung eines Objektes durch Benennung und Belegung seiner Eigenschaften und seines Verhaltens an Ort und Stelle der Verwendung.
2.3.2 Slots und Parent-Slot
Objekte werden in prototypenbasierten Sprachen als eine Menge von sog. Slots aufgefasst.2 Ein Slot meint dabei ein einfaches Schl
ussel-Wert-Paar (key-value-pair ), entspricht also der Datenstruktur der Map. Der Zugri auf einen Wert, der sowohl Daten
(Zustand des Objekts) als auch Funktionen (Verhalten des Objekts) beinhalten kann,
erfolgt u
ussel [7, S. 96 f.].
ber einen Schl
In einigen Sprachen verf
ugen Objekte u
ber einen speziellen Slot, den sog. Parent-Slot.
2

Der Begri des Slots stammt aus dem Bereich der k


unstlichen Intelligenz und bezeichnet einfach
eine Menge von Daten, die zu einer bestimmten Situation (frame) gehoren. Siehe [11] f
ur weitere
Informationen.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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

Abbildung 1: Schematische Darstellung eines Objektes mit


n+1 Slots, Quelle: Eigene Darstellung
bei der Realiserung der sog. Delegation, die im nachsten Abschnitt theoretisch erlautert
und in Abschnitt 3.4 an praktischen Beispielen in der Programmiersprache JavaScript
demonstriert wird [10].
2.3.3 Delegation
In der klassenbasierten Programmierung entsprechen Klassen Bauplanen f
ur Objekte.
Eine Klasse definiert dabei eine Menge von Attributen, u
ber die jede ihrer Instanzen
verf
ugt. Die Belegung dieser Attribute mit konkreten Werten geschieht individuell auf
der Ebene der Instanzen d.h. jede Instanz verf
ugt u
ber ihren eigenen Zustand.3

Klassen definieren dar


uber hinaus das Verhalten ihrer zuk
unftigen Instanzen. Anderungen am Verhalten der Klasse haben zur Folge, dass sich das Verhalten aller konkreten Objekte dieser Klasse andert. Mochte man ein Objekt erzeugen, dass sich durch
zusatzliche Attribute oder ein besonderes Verhalten auszeichnet, so muss eine Spezialisierung in Form einer Subklasse erzeugt werden, die alle Eigenschaften der Basisklasse
erbt und um zusatzliche Eigenschaften erweitert wird [8, 7, S. 94 .].
Eine Alternative zur klassenbasierten Vererbung bieten prototypenbasierte Sprachen
in Form der sog. Delegation. Erhalt ein Objekt in einer Programmiersprache, die Delegation unterst
utzt, eine Nachricht wie z.B. den Abruf einer Eigenschaft, so versucht
es zunachst selbst diese Nachricht zu beantworten. Ist dies nicht moglich, so wird die
Nachricht an das Objekt im Parent-Slot des empfangenden Objektes weitergeleitet.
Dieser Vorgang kann nun solange wiederholt werden bis die Eigenschaft in einem der
Delegaten gefunden wird, oder das Ende der Kette erreicht wird. Mochte nun ein KindObjekt einen Attributwert andern, der von seinem Prototypen-Objekt stammt, reicht
es aus diesen Wert lokal im Kind-Objekt zu setzen.
Dieser Sachverhalt soll noch einmal in Abbildung 2 verdeutlicht werden. Clyde ist der
Prototyp von Fred, da Freds Parent-Slot u
ber eine Referenz auf das Objekt von Clyde
verf
ugt. Wird nun Fred nach der Anzahl seiner Stozahne gefragt, so wird die Anfrage
implizit an Clyde delegiert, der als Prototyp von Fred mit 2 antwortet. Wird Fred

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

Abbildung 2: Schematische Darstellung der Delegation,


Quelle: Eigene Darstellung
In Abschnitt 3.4 wird gezeigt, wie der Mechanismus der Delegation in JavaScript genutzt werden kann, um Vererbung zu simulieren. Der umgekehrte Fall ist allerdings
nicht moglich. Dies liegt an den unterschiedlichen Arten, wie in den prototypen- und
klassenbasierten Sprachen mit der Selbstreferenz self bzw. this umgegangen wird.
In klassenbasierten Sprachen bezieht sich die Variable self immer auf den Empfanger

Abbildung 3: Forwarding vs. Delegation,


Quelle: http://bit.ly/1yGzr2y
eines Methodenaufrufes. Man nennt diese Art von Aufruf auch Forwarding.4 Es ist also
nicht moglich Methoden so aufzurufen, dass self ein anderes Objekt referenziert. Die
Delegation der prototypenbasierten Sprachen ermoglicht dies hingegen, da die Variable
self in diesem Fall nicht den Aufgerufenen (Client), sondern den Aufrufer (Server )
referenziert. Neben dem Zustand kann so auch das Verhalten des Prototypen wiederverwendet werden [8].
2.3.4 Vielfalt prototypenbasierter Programmiersprachen
Am Ende dieses Kapitels soll kurz anhand der beiden Sprachen Kevo und Omega
verdeutlicht werden, dass die vorgestellten Eigenschaften nicht notwendigerweise f
ur
alle Implementierungen prototypenbasierter Sprachen gelten.
Kevo: Die Programmiersprache Kevo verf
ugt weder u
ber einen Parent-Slot noch
den Mechanismus der Delegation. Wird ein Objekt geklont, so wird eine unabhangige Kopie, die in keinerlei Beziehung zum Parent steht, erzeugt. Es steht

dem Entwickler danach frei beliebige Anderungen


an dem neu erzeugten Objekt
durchzuf
uhren. Objekte konnen zudem in Gruppen zusammengefasst werden, die
ebenfalls durch sog. modifications verandert werden konnen [7, S. 100 .].
Omega: Beim Entwurf der Sprache Omega wurde Wert auf Typsicherheit gelegt. Man entschied sich daher f
ur die Nutzung einer statischen Typpr
ufung in
4

In der klassenbasierten Programmierung werden die Begrie Delegation und Forwarding haufig
synonym verwendet. Gemeint ist meist Letzeres, siehe [12, S. 116 f.].

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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 Geschichte JavaScripts


Die Programmiersprache JavaScript wurde im Jahr 1995 von Brendan Eich, einem
damaligen Mitarbeiter des Unternehmens Netscape Communications, erfunden und
umgesetzt. Eine Besonderheit dieser Sprache ist die Tatsache, dass Eich sie in in wenigen Tagen entwickelt hat, und sie dennoch bis heute weitergenutzt wird [14].
Eich bediente sich dabei an Sprachkonzepten, die er f
ur besonders n
utzlich empfand.
Anders als der Name der Sprache vermuten lasst, wurde er nicht durch die Sprache
Java, sondern durch die prototypenbasierte Sprache Self und die funktionalen Sprachen
Scheme bzw. Lisp inspiriert. Seine Implementierung fand im selben Jahr Einzug in den
Netscape Navigator,5 und wurde bereits ein Jahr spater von Microsoft kopiert und als
JScript im Internet Explorer angeboten [15, S. 1, 14].

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

Damals noch unter dem Namen LiveScript.


Laut Brendan Eich war die Einigung auf diesen Namen noch tragischer als die tr
ugerische Bezeichnung JavaScript, da ECMA nach einer Hautkrankeit klinge.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

3.1.2 JavaScript als missverstandene Sprache


Douglas Crockford, der mit seinem Werk JavaScript - The Good Parts, mageblich

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

3.2 Objekte in JavaScript


JavaScript verf
ugt neben den primitiven Datentypen Number, String und Boolean,
den besonderen Typen undefined und null u
ber Objekte. Zwei besondere Objekte,
die durch die verschiedenen Laufzeitumgebungen bereitgestellt werden, sind Funktionsobjekte (Function) und Felder (Array) [15, S. 29]. Der Aufbau eines Objektes
7

Stand November 2014

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

Listing 2: Objekterzeugung mittels Konstruktoraufruf


1
2
3
4
5
6
7
8
9
10

function Elephant ( name ) {


this.name = name;
this.numberOfTusks = 2;
this.makeNoise = function () {
console.log ( " Tooeroooe ! " ) ;
}
}
var clyde = new Elephant ( " Clyde " ) ;
clyde instanceof Elephant; // true

Analog zum vorherigem Beispiel wird in Listing 1 ein Objekt namens Clyde erzugt,

allerdings erkennt man am Schl


usselwort new in Zeile 9, dass ein Konstruktoraufruf zur
Erzeugung verwendet wird. Ein solcher Aufruf hat eine Menge von Operationen zur
Folge, die auf den ersten Blick nicht ersichtlich sind und daher an dieser Stelle noch
einmal einzeln aufgeschl
usselt werden sollen [18, S. 21, 22]:
1. Es wird ein neues (leeres) Objekt erstellt.
2. Die Prototypen-Eigenschaft des Objektes wird gesetzt. Was dies konkret bedeutet, und welcher Wert der Eigenschaft zugewiesen wird, wird detailliert in Kapitel
3.3 erlautert.
3. Die Variable this referenziert das neue Objekt und ermoglicht so eine Modifikation seiner Eigenschaften.
4. Sollte die Konstruktorfunktion keinen explizit R
uckgabewert benennen, so wird
das neue Objekt zur
uckgegeben.
Das Konzept der Konstruktoren wird haufig kritisiert. Konstruktoren erwecken durch
ihren Namen und ihre Syntax den Eindruck JavaScript verf
uge u
ber Klassen. Die Verwendung des Schl
usselwortes new in Kombination mit Zuweisungen an die Variable
this innerhalb der Konstruktorfunktionen erinnern stark an die Verwendung von Konstruktoren in klassenbasierten Sprachen wie Java oder C#, und f
uhren bei unerfahrenen
Programmierern und JavaScript-Anfangern zu vermeidbaren Verstandnisproblemen.
An dieser Stelle sei zudem noch einmal erwahnt, dass Konstruktoren gewohnliche Funktionen sind, die auch ohne das Schl
usselwort new aufgerufen werden konnen. Leider
wird in diesem Fall die Selbstreferenz this an das globale Objekt gebunden, was unter
Umstanden zu schwer nachvollziehbaren Fehlern f
uhren kann (siehe Listing 3).
Die Konsequenz ist, dass einige Autoren von der Verwendung von Konstruktoraufrufen
abraten und stattdessen dazu appellieren, die u
brigen Formen der Objekterzeugung zu
nutzen, die charakteristisch f
ur prototypenbasierte Sprachen sind [20, S. 30].
Listing 3: Fehlerhafte Objekterzeugung
1
2
3
4
5
6
7

function Elephant ( name ) {


this.name = name;
}
var clyde = Elephant ( " Clyde " ) ; // new fehlt
console.log ( clyde.name ) // Fehler
console.log ( window.name ) // " Clyde "

Seminararbeit zum Kurs 1908 - Thema: JavaScript

10

3.2.3 Klonung und Erweiterung


In Abschnitt 2.3.1 haben wir bereits die Moglichkeit der Objekterzeugung durch Klonung bzw. Erweiterung kennengelernt. ECMAScript verf
ugt seit Version 5.1 u
ber die
Funktion Object.create, die beide Arten der Objekterzeugung ermoglicht. Da auch
Object.create ausgiebig Gebrauch von Prototypen macht, wird an dieser Stelle auf
die ausf
uhrliche Erlauterung verzichtet und auf die spatere Betrachtung in Kapitel 3.5.2
verwiesen.

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

Seminararbeit zum Kurs 1908 - Thema: JavaScript


3

11

Obj e c t . g e t P r o t o t y p e O f ( Object.prototype ) === null; // true

3.3.2 [[Prototype]] und Konstruktoren


In Abschnitt 3.2.2 wurde bereits gezeigt, dass die Objekterzeugung mittels Konstruk
toraufruf ebenfalls Anderungen
am Prototypen eines Objeks durchf
uhrt. Dem neuen Objekt, das durch den Aufruf erstellt wurde, wird als [[Prototype]] der Wert
der Prototyp-Eigenschaft (.prototype) des Konstruktors zugewiesen. Anders ausgedr
uckt: Die interne Prototypeneigenschaft ([[Prototype]]) referenziert bei Objekten, die mittels Konstruktoraufruf erzeugt wurden, das selbe Objekt wie die explizite
Prototypen-Eigenschaft .prototype der Konstruktor-Funktion. Listing 5 verdeutlicht
diesen Sachverhalt an einem praktischen Beispiel.

Listing 5: Anderungen
an Prototyp-Objekten
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

function Elephant ( name ) {


this.name = name;
}
console.log ( E le ph an t. pro to ty pe ) ; // {}
E l e p h a n t . p r o t o t y p e . n u m b e r O f T u s k s = 2;
E l e p h a n t . p r o t o t y p e . m a k e N o i s e = function () {
console.log ( " Tooeroooe ! " ) ;
}
var clyde = new Elephant ( " Clyde " ) ;
clyd e . nu m b er O f Tu s k s === 2; // true
clyde.makeNoise () ; // " Tooeroooe !"
Obj e c t . g e t P r o t o t y p e O f ( clyde ) === E le ph an t. pr oto ty pe // true

Es wurde bereits mehrfach erwahnt, dass Konstruktoren in JavaScript einfache Funktionen sind. Da Funktionen selbst first-class citizens, also Objekte sind, verf
ugen

sie selbst auch u


ber Eigenschaften. Eine dieser Eigenschaften ist, die bereits erwahnte
Eigenschaft prototype, die in Zeile 5 zunachst auf eine leeres Objekt verweist und bei
Bedarf auch geandert werden kann. In den Zeilen 7-10 wird eben dieses PrototypenObjekt modifiziert und erhalt neben einem Attribut eine neue Funktion. Wird daraufhin ein neues Objekt mittels Konstruktoraufruf erzeugt, so sieht man (in den Zeilen 13
und 14), dass dieses Objekt ebenfalls u
ugt.
ber die Eigenschaften des Prototypen verf
Abbildung 4 stellt zur Verdeutlichung das resultierende Objektgeflecht noch einmal
grafisch dar.9

3.4 Delegation in JavaScript


Es stellt sich nun die Frage, wie im vorherigen Abschnitt ein Objekt auf die Eigenschaften seines Prototypen zugreifen konnte. Dieser Mechanismus wird in JavaScript mittels
9

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

Seminararbeit zum Kurs 1908 - Thema: JavaScript

12

Abbildung 4: Prototypen in JavaScript, Quelle: Eigene


Darstellung
Delegation realisiert und haufig auch als Prototype-Chaining bezeichnet. Wird eine Eigenschaft eines beliebigen Objektes abgefragt, so pr
uft das Objekt zunachst lokal, ob
es u
ugt. Ist dies der Fall, so wird die entsprechende Operation
ber diese Eigenschaft verf
durchgef
uhrt. Schlagt der Versuch allerdings fehl, so wird der Zugri an das Objekt
weitergeleitet, das mittels [[Prototype]] referenziert wird. Dieser Mechanismus wird
so lange fortgesetzt bis Object.prototype erreicht wird. Sollte auch dort die gesuchte Eigenschaft nicht gefunden werden, so wird abgebrochen, da Object.prototype
bekanntlich u
ugt [19, S. 71].
ber keinen weiteren Prototypen verf
Listing 6: Delegation in JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

function Elephant ( name ) {


this.name = name;
}
E l e p h a n t . p r o t o t y p e . n u m b e r O f T u s k s = 2;
E l e p h a n t . p r o t o t y p e . m a k e N o i s e = function () {
console.log ( this.name + " says: Tooeroooe ! " ) ;
}
var clyde = new Elephant ( " Clyde " ) ;
var fred = new Elephant ( " Fred " ) ;
El ep h a n t . p r o t o t y p e . e a t = function () {
console.log ( " nom nom nom " ) ;
}
clyde.eat () ; // " nom nom nom "
fred.numberOfTusks = 1; // poor fred ;(
clyd e . nu m b er O f Tu s k s === 2; // true
fred.numberOfTusks === 1; // true
fred.makeNoise () ; // " Fred says: Tooeroooe !";

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-

Seminararbeit zum Kurs 1908 - Thema: JavaScript

13

typen werden zwei konkrete Elefanten erzeugt.


In den Zeilen 13-15 wird der Prototyp der beiden Elefanten nachtraglich, d.h. nachdem
die beiden Objekte bereits erzeugt wurden, um die Funktion eat() erweitert. In Zeile 17 wird nun die nachtraglich hinzugef
ugte Funktion auf einem der beiden Objekte
erfolgreich aufgerufen. Dieser Sachverhalt verdeutlicht, dass es sich bei einem Prototypen um ein gewohnliches Objekt handelt, das beliebig modifiziert werden kann. Es
zeichnet sich nur als Prototyp aus, weil es durch [[Prototype]] eines beliebigen anderen Objektes referenziert wird. Der Mechanismus der Delegation sorgt daf
ur, dass die
beiden Objekte clyde und fred indirekt u
ber
den
Zustand
und
das
Verhalten
ihres

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.

Abbildung 5: Delegation in JavaScript, Quelle: Eigene


Darstellung

3.5 Vererbung in JavaScript


Bisher wurde nur die Beziehung zwischen einem Objekt und seinem Prototypen betrachtet. Dieser einstufige Zusammenhang entspricht im Wesentlichen der Beziehung
zwischen einem Objekt und seiner Klasse in der klassenbasierten Programmierung.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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

function Mammal ( name ) {


this.name = name;
}
Mamm a l . p r o t o t y p e . e a t = function () {
console.log ( " nom nom nom " ) ;
}
function Elephant ( name ) {
this.name = name;
this.numberOfTusks = 2;
}
Elephant.prototype = new Mammal () ;
E l e p h a n t . p r o t o t y p e . m a k e N o i s e = function () {
console.log ( this.name + " says: Tooeroooe ! " ) ;
}
var clyde = new Elephant ( " Clyde " ) ;
clyde.name === " Clyde " ; // true
clyd e . nu m b er O f Tu s k s === 2; // true
clyde.eat () ; // " nom nom nom "
clyde.makeNoise () ; // " Clyde says: Tooeroooe !") ;

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

Elephant.prototype = Mammal.prototype; ist u


brigens auch keine Option, da dadurch alle
S
augetiere zu Elefanten w
urden und umgekehrt.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

15

Abbildung 6: Pseudo-klassenbasierte Vererbung, Quelle:


Eigene Darstellung
den Objekten, die konkrete Instanzen reprasentieren, und Objekten, die Klassen reprasentieren, statt.
Auf den ersten Blick konnte man ebenfalls meinen, es fande, bedingt durch den Aufruf
in Zeile 14, eine Verkettung von Konstruktoraufrufen statt. Dies erweist sich allerdings
als falsch, denn wird ein neues Objekt mit new Elephant() erstellt, so wird keineswegs
der Konstruktor des Saugetiers (Zeile 1) aufgerufen, stattdessen m
ussen die geerbten
Attribute in der Konstruktorfunktion der Subklasse wiederholt werden (Zeile 10).11

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

if ( typeof Object.create ! == ' function ') {


Object.create = function ( o ) {

In Abschnitt 3.5.3 wird gezeigt, wie man zumindest diese Unschonheit beseitigen kann.

Seminararbeit zum Kurs 1908 - Thema: JavaScript


3
4
5
6
7
8
9

16

function F () {}
F.prototype = o;
return new F () ;
};
}
newObject = Object.create ( oldObject ) ;

Listing 8 zeigt eine mogliche Implementierung der Methode Object.create() und


gleichzeitig einen sog. Polyfill, einen Quelltext, der dazu dient Browserinkompatibilitaten zu schlieen, indem eine proprietare Funktionalitat mit bereits standardisierten
Mitteln nachgestellt wird. In diesem konkreten Fall handelt es sich um eine Implementierung, die eine eingeschrankte Version von Object.create() bereitstellt [23, S.
91, 20, S. 22]. In Zeile 3 wird ein temporarer Konstruktor erstellt, dessen prototypeEigenschaft im nachsten Schritt mit dem u
bergebenen Objekte o u
berschrieben wird.
Zeile 5 hat zur Folge, dass ein neues Objekt zur
uckgegeben wird, dessen [[Proto12
type]]-Eigenschaft auf das u
bergebene
Objekt
o
verweist.

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

var clyde = { name : " Clyde " , numberOfTusks : 2 }


// " cloning "
var fred = Object.create ( clyde ) ;
fred.name = " Fred " ;
fred.numberOfTusks === 2; // true
fred.african = true;
// extending
var bonnie = Object.create ( fred , {
isMatriarch: {
configurable: true ,
enumerable: true ,
value: true ,
writable: true
},
name: {
configurable: true ,
enumerable: true ,
value: " Bonny " ,
writable: true
}
}) ;
bonnie.name === " Bonny " ; // true
bonnie.isMatriarch === true; // true

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

Laufzeitumgebeungen, die ECMAScript 5.1 unterst


utzen, bieten nat
urlich native Implementierungen dieser Funktion an.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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.

Abbildung 7: Prototypenbasierte Vererbung, Quelle: Eigene


Darstellung

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

function Mammal ( name ) {


this.name = name;
}
function Elephant ( name ) {
Mammal.call ( this , name ) ;
this.numberOfTusks = 2;
}
Elephant.prototype = Object.create ( Mammal.prototype ) ;
E l e p h a n t . p r o t o t y p e . m a k e N o i s e = function () {
console.log ( this.name + " says: Tooeroooe ! " ) ;
}

Seminararbeit zum Kurs 1908 - Thema: JavaScript


15
16
17
18

18

var clyde = new Elephant ( " Clyde " ) ;


clyde.name === " Clyde " ; // true
clyd e . nu m b er O f Tu s k s === 2; // true
clyde.makeNoise () ; // " Clyde says: Tooeroooe !") ;

Die beiden wesentlichen Unterschiede zur pseudo-klassenbasierten Version werden in


Zeile 10 ersichtlich, da dort der Konstruktoraufruf von Mammal durch einen Aufruf von
Object.create(Mammal.prototype) ersetzt wurde. Dies bringt den Vorteil, dass die
bereits erwahnte Vermischung zwischen Instanzobjekten und Klassenobjekten aufgelost
wird, so dass zwei sauber voneinander getrennte Hierarchien gepflegt werden konnen.
Zudem erfolgt kein unnotiger Aufruf des Konstruktors Mammal, der zu unvorhersehbaren Programmabst
urzen oder Nebeneekte f
uhren kann. An dieser Stelle sei noch
auf die Zeile 6 hingewiesen, die auch so im Beispiel der pseudo-klassenbasierten Version hatte auftauchen konnen. Es handelt sich dabei um einen indirekten Aufruf des
Konstruktors Mammal, bei dem der Inhalt des ersten Arguments an die lokale Variable
this innerhalb des Konstruktors gebunden wird. In diesem Fall heit das u
bergebene
Argument ebenfalls this, da es ja das Objekt reprasentiert, das durch den Aufruf new
Elephant() erzeugt wurde, und entsprechend initialisiert werden soll.
3.5.4 Mixins als Alternative
Der Vollstandigkeit halber soll hier noch eine Alternative zur Vererbung gezeigt werden,
die ohne Prototypen arbeitet. Diese Alternative stellen die sog. Mixins dar, die kurz
am Quelltextbeispiel 11 nachvollzogen werden sollen [19, S. 84 f.].
Listing 11: Beispiel f
ur die Implementierung eines Mixins
1
2
3
4
5
6
7
8

function mixin ( receiver , supplier ) {


for ( var property in supplier ) {
if ( s u p p l i e r . h a s O w n P r o p e r t y ( property ) ) {
receiver [ property ] = supplier [ property ]
}
}
return receiver;
}

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.

4 JavaScript in der Praxis


Nachdem im vorherigen Kapitel JavaScript und dessen Prototypen vorgestellt wurden,
befasst sich dieser Teil der Arbeit mit der professionellen Nutzung von JavaScript in

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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.

4.1 Das jQuery-Projekt


Wichtigstes Merkmal der Implementierung von JavaScript in Browsern ist die sog. Document Object Model-API, die bereits 1998 durch das World Wide Web Consortium
(W3C) standardisiert wurde und einen einheitlichen Zugri auf die Elemente eines
HTML-Dokumentes ermoglicht. Diese Schnittstelle benennt diverse Funktionen, mit
denen die hierarchisch angeordneten Elemente einer XML-Struktur modifiziert und
durchlaufen werden konnen [29].
In der Vergangenheit implementierten Browserhersteller diese Schnittstelle in ihren
Produkten und erweiterten sie haufig um eigene Funktionen, die mit der Zeit haufig
selbst in den Standard gelangten. Leider wiesen viele Browser Eigenheiten bei der Implementierung auf, die von den Nutzern haufig durch Zwischenlosungen (z.B. der bereits
vorgestellte Polyfill) kompensiert werden mussten. Die Folge war, dass im Laufe der
Zeit Bibliotheken entstanden, die diese einzelnen Browserinkompatibilitaten kapselten
und haufig u
ugten.
ber weitere, eigene Funktionen verf
Eine dieser Erweiterungen, die von vielen Entwicklern begr
ut wurde, war es CSSSelektoren zur Auswahl von Elementen des DOMs zu nutzen, und so die unflexiblen
Funktionen des W3C-Standards zu verbessern. Cascading Stylesheets boten bereits in
der Version 1 im Jahr 1996 eine vielseitige Moglichkeiten auf die einzelnen Elemente eine HTML/XML-Dokuments zuzugreifen. Wahrend der Standard des W3C nur
einen Zugri auf DOM-Elemente u
ber ihren Typ oder das Attribut ID vorsieht, unterst
utzten CSS-Selektoren weitere Zugrismoglichkeiten u
ber Klassen, Pseudoklassen
und Pseudoelemente [30]. Dar
uber hinaus ist die die Verwendung der Selektoren vielen
Entwicklern gut bekannt.
Der Entwickler John Resig war ebenfalls von dieser Idee u
berzeugt, bemangelte allerdings ihre Ausf
uhrung in Form der damals verwendeten Bibliotheken (z.B. behaviour.js). Resig entwicklelte daraufhin seine eigene Bibliothek namens jQuery, die im
August 2005 veroentlich wurde und bis heute aktiv gepflegt und genutzt wird. Kernbestandteil der Bibliothek war der von ihm entwickelte Code zur Nutzung von CSSSelektoren in JavaScript, um einzelne Element oder Gruppen von Elementen selektieren
zu konnen [31].13 Wie effizient diese Mechanik im Vergleich zu herkommlichen JavaScript ist, zeigt Listing 12.
Listing 12: Vergleich JavaScript vs. jQuery
1
2
3
4
5
6
13

// 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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript


7
8
9
10
11
12
13

20

var httpRequest = new XMLHttpRequest ()


h t t p R e q u e s t . o n r e a d y s t a t e c h a n g e = function ( data ) {
// Verarbeitung
}
h t t p R e q u e s t . s e t R e q u e s t H e a d e r ( ' Content-Type ' , ' application /
x - w w w - f o r m - u r l e n c o d e d ')
httpRequest.open ( ' POST ' , ' www.example.com / login ')
httpRequest.send ( ' username= ' + en co de UR IC om po ne nt ( ' fred ') )

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.

Animationen und Eekte: Um Nutzer auf Anderungen


innerhalb des Dokumentes aufmerksam zu machen und ggf. u
ber Erfolg und Misserfolg einer Aktion
zu informieren, wird eine Menge von Animationen und Eekten angeboten.15
AJAX: AJAX steht f
ur Asynchronous JavaScript and XML und beschreibt eine Technik basierend auf dem XMLHttpRequest-Objekt, einer Funktionalitat
14
15

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

21

Abbildung 8: Verbreitung verschiedener JavaScript


Bibliotheken [Stand 15.12.2014], Quelle: w3techs.com
des Browsers, die asynchrone HTTP-Anfragen an einen Server ermoglicht. Moderne Webanwendungen, die in Aufbau und Funktion an klassische DesktopApplikationen erinnern (sog. Single Page Applications), waren ohne AJAX nicht
moglich. Detaillierte Informationen zum Thema AJAX konnen [34, Kap. 18] entnommen werden. JQuery bietet mit seinem ajax-Objekt eine vielseitig nutzbare
Schnittstelle zur Verwendung von AJAX innerhalb diverser Laufzeitumgebungen.
Ein Beispiel f
ur einen solchen AJAX-Aufruf wurde bereits mit der Methode post
un Zeile 2 von Listing 12 gebracht.
F
ur den Entwickler ergeben sich aus der Nutzung von jQuery einige Vorteile [35, S.
105 .]:
Weniger Quelltext: Write less, do more lautet das Motto von jQuery. Das

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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.

4.2 Untersuchung ausgew


ahlter Quelltextpassagen
Der Erfolg der jQuery-Bibliothek hangt unter anderem stark von seiner einfachen Verwendung und der bereits erwahnten Erweiterbarkeit ab. Diese beiden Erfolgsfaktoren
waren ohne die eektive Nutzung JavaScripts funktionaler und prototypenbasierter
Spracheigenschaften sicherlich nicht moglich gewesen. An ausgewahlten Teilen des Projektquelltextes 16 soll diese Aussage belegt werden.

4.2.1 Initialisierung des jQuery-Objekts


Kern der Implementierung von jQuery ist das sog. jQuery-Objekt. Es handelt sich
dabei um ein JavaScript-Objekt, das alle Bibliotheksmethoden vereint. Bereits das
Initialisieren diese Objektes macht ausgiebig Gebrauch von JavaScripts funktionalen
Eigenschaften.
16

Stand 19.11.2014, Version 2.1.1

Seminararbeit zum Kurs 1908 - Thema: JavaScript

23

Listing 13: Erstmalige Erzeugung des jQuery-Objektes


1
2
3
4
5

( function ( global , factory ) {


// call factory
}( typeof window ! == " undefined " ? window : this , function ( window ,
noGlobal ) {
// define factory
}

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

// Define a local copy of jQuery


jQuery = function ( selector , context ) {
// The jQuery object is actually just the init constructor '
enhanced '
// Need init if jQuery is called ( just allow error to be thrown
if not included )
return new jQuery.fn.init ( selector , context ) ;
},
...
init = jQuery.fn.init = function ( selector , context ) {
// initialization
...
};
// Give the init function the jQuery prototype for later
instantiation
init.prototype = jQuery.fn;

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

24

4.2.2 Verwendung von Prototypen


Bei jQuery.fn handelt es sich lediglich um eine Referenz auf jQuery.prototype, um
den Code u
bersichtlicher und kleiner zu halten. Dieser Prototyp beinhaltet alle wichtigen Funktionen der Bibliothek, die in der API des Projektes aufgelistet werden. Der
Groteil der mehr als 10.000 Zeilen Quelltext beschreibt diese Funktionen und bindet
sie an das Prototypen-Objekt. Die Bindung der Funktionalitat an jQuery.fn bietet
zwei groe Vorteile:
1. Der Mechanismus der Objekterzeugung bleibt performant und ressourcenschonend. Wird ein neues Objekt erstellt, so muss lediglich die Referenz auf den
existierenden Prototypen kopiert, und nicht jede der vielen Bibliotheksfunktionen neu erzeugt werden (siehe letzte Zeile in Listing 15).
2. Die Erweiterung der Bibliothek gestaltet sich besonders einfach, da neue Funktionen oder Eigenschaften nur an den Prototypen angef
ugt werden m
ussen, wodurch
alle bereits existierenden und zuk
unftigen Objekte um diese Merkmale erganzt
werden.
Da sich die Implementierung der Funktionalitat eigentlich im Prototypen-Objekt befindet, macht jQuery ausgiebig vom Prinzip der Delegation Gebrauch. Wir betrachten
dazu in Listing 16 die Funktion before, die es ermoglicht ein DOM-Element vor einem
anderen einzuf
ugen.
Listing 16: Beispiel f
ur die Verwendung von Delegation in der jQuery Bibliothek
1
2
3
4
5
6
7

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.

Seminararbeit zum Kurs 1908 - Thema: JavaScript

25

Callback-Funktionen: Ereignisse und ihre Behandlung spielen in JavaScript


im Allgemeinen und in jQuery im Speziellen eine wichtige Rolle, da durch die
Verwendung im Browser auf eine Vielzahl von Benutzer- und Netzwerkereignisse
reagiert werden muss. Hierbei kommt haufig die funktionale Programmierung
zur Anwendung, da mit ihr Ereignisfunktionen als Parameter u
bergeben, und bei
Auftritt des Ereignisses an Ort und Stelle ausgef
uhrt werden konnen.
Wrapped Sets: Eine Entwurfsentscheidung, die die Verwendung der Bibliotheksfunktionen stark vereinfacht, ist die der sog. Wrapped Sets. Ein jQueryObjekt, das mit einem Selektor initialisiert wird, durchsucht das Dokument nach
Elementen, die diesem Selektor entsprechen. Das Ergebnis des Suchvorgangs ist
eine beliebig groe Menge von jQuery-Objekten, auf die alle bekannten Bibliotheksfunktionen angewendet werden konnen, wodurch eine explizite Iteration
u
ber die Ergebnismenge entfallt.
Verkettung von Funktionsaufrufen: Die Funktionen des jQuery-Objektes geben haufig das Objekt selbst zur
uck, und ermoglichen so eine einfache Verkettung
von Bibliotheksfunktionen.
4.2.4 Praxisbeispiel
Die aufgezahlten Besonderheiten sollen abschlieend in Listing 17 an einem eigenen
Quelltextbeispiel erlautert werden.
Listing 17: Verwendung von jQuery zur DOM-Manipulation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<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

WrappedSet aus jQuery-Objekten, die u


ugen, erzeugt. Jedem
ber das HTML-Tag li verf

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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

(Zeile 7). Der Aufruf dieser beiden Anderungen


erfolgt verkettet in Zeile 7. Mit dem
Aufruf $(this) zeigt Zeile 7 ebenfalls ein Beispiel f
ur die Konvertierung (Wrap) eines
Standard-DOM-Objektes zu einem jQuery-Objekt.
An diesem kurzen Beispiel sieht man, wie effizient sich die Arbeitet mit der Bibliothek
gestaltet. Mit lediglich vier verstandlichen Zeilen Quelltext wurden drei DOM-Elemente
optisch verandert, animiert und um eine Ereignisbehandlung erganzt, nachdem gepr
uft
wurde, ob sie bereits vom Browser korrekt geladen wurden.

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

Vor Anfertigung dieser Arbeit z


ahlte sich der Autor ebenfalls dazu.
Stand: 02.12.2014
20
Die Benennung des Schl
usselwortes selbst empfindet der Autor als sehr zweifelhaft.
19

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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

Schematische Darstellung eines Objektes mit n+1 Slots, Quelle: Eigene


Darstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schematische Darstellung der Delegation, Quelle: Eigene Darstellung .
Forwarding vs. Delegation, Quelle: http://bit.ly/1yGzr2y . . . . . .
Prototypen in JavaScript, Quelle: Eigene Darstellung . . . . . . . . . .
Delegation in JavaScript, Quelle: Eigene Darstellung . . . . . . . . . . .
Pseudo-klassenbasierte Vererbung, Quelle: Eigene Darstellung . . . . .
Prototypenbasierte Vererbung, Quelle: Eigene Darstellung . . . . . . .
Verbreitung verschiedener JavaScript Bibliotheken [Stand 15.12.2014],
Quelle: w3techs.com . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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/

Seminararbeit zum Kurs 1908 - Thema: JavaScript

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).

Seminararbeit zum Kurs 1908 - Thema: JavaScript

29

[25] Draft ECMA-262 6th Edition. 2014. url: http://mzl.la/1rTkdmK (besucht am


02. 12. 2014).
[26] Mozilla Developer Network (MDN) - Object.prototype. 2014. url: http://mzl.
la/1oAlm1C (besucht am 27. 11. 2014).
[27] Joost Diepenmaat. Constructors Considered Mildly Confusing. 2013. url: http:
//bit.ly/1lmComJ (besucht am 15. 11. 2014).
[28] Mozilla Developer Network (MDN) - Introduction to Object-Oriented JavaScript.
2014. url: http://mzl.la/J1gPG5 (besucht am 15. 11. 2014).
[29] W3C. Document Object Model. 2005. url: http://www.w3.org/DOM/ (besucht
am 18. 11. 2014).
[30] W3C. Cascading Style Sheets, level 1. 2008. url: http://www.w3.org/TR/RECCSS1/ (besucht am 18. 11. 2014).
[31] John Resig. Selectors in JavaScript. 2005. url: http://bit.ly/1voIe8X.
[32] jQuery Foundation. jQuery API. 2014. url: http://api.jquery.com (besucht
am 18. 11. 2014).
[33] jQuery Foundation. History. 2014. url: https://jquery.org/history/ (besucht am 18. 11. 2014).
[34] Stefan Koch. JavaScript - Einf
uhrung, Programmierung und Referenz. 6. Aufl.
Koln: Dpunkt-Verlag, 2011. isbn: 978-3-898-64731-1.
[35] David Sawyer McFarland. JavaScript & jQuery: The Missing Manual. 3. Aufl.
OReilly Media, Okt. 2014. isbn: 978-1-491-94707-4.
[36] ECMA. ECMAScript 5.1, Identifier Names and Identifiers. 2014. url: http :
//bit.ly/15MnkbU (besucht am 01. 12. 2014).

Das könnte Ihnen auch gefallen