26.02.2014 Aufrufe

LinuxUser Programmieren (Vorschau)

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

Javascript<br />

SCHWERPUNKT<br />

nierte Funktionen (innere Funktionen)<br />

stets auf Variablen der sie<br />

umgebenden Funktion zugreifen,<br />

die äußere Funktion aber natürlich<br />

nicht auf die der inneren: Das<br />

würde zu einem einzigen durchgängigen<br />

Variablen-Gültigkeitsbereich<br />

führen.<br />

Die beiden Aufrufe von greeter1.<br />

sayHello() und greeter2.sayHello()<br />

zeigen, dass der Wert aus dem Parameter<br />

who in toGreet gespeichert<br />

bleibt, obwohl die Funktion Greeter<br />

schon gelaufen ist.<br />

Das liegt daran, dass an Variablen<br />

gebundene Funktion in Javascript<br />

sozusagen ihre Laufzeitumgebung<br />

mit einpacken. Konkret<br />

heißt das: Alle Variablen aus der<br />

Umgebung von sayHello, auf die<br />

die Funktion zugreift, verweilen<br />

im Speicher, solange die Funktion<br />

selbst an eine Variable gebunden<br />

bleibt. Hierfür zeichnen greeter1<br />

und greeter2 verantwortlich, die<br />

sayHello() als Attribut enthalten.<br />

Diese Technik nennt sich Closure<br />

(Einschluss).<br />

Das Prinzip des Closure ist an<br />

sich einfach: Der Javascript-Interpreter<br />

geht den Code vor dem<br />

Ausführen einmal durch und notiert<br />

sich, welche Stellen des Programms<br />

auf welche Variablen zugreifen.<br />

Bei der Frage, wie lange<br />

Variablen im Speicher bleiben,<br />

gilt die Regel: Alles, was noch gebraucht<br />

wird, bleibt im Speicher.<br />

Eltern und Kind<br />

Nun bleibt nur noch das Schlüsselwort<br />

new zu erläutern, das aus<br />

der Funktionsdefinition Greeter<br />

die zwei Objektinstanzen greeter1<br />

und greeter2 macht, die verschiedene<br />

Werte für toGreet beherbergen.<br />

new Funktion() bewirkt zweierlei:<br />

Es erzeugt ein Objekt und<br />

es führt function() aus.<br />

Dabei sind function() und das<br />

Objekt identisch. Die Funktion<br />

verändert sich also bei der Attributzuweisung<br />

this.Attributname<br />

selbst. Nach dem Ausführen der<br />

Funktion bindet der Aufruf new<br />

das Funktionsobjekt (das mit der<br />

Funktion identische Objekt) an<br />

die Variable greeter1 oder greeter2,<br />

gerade so, als würde die Funktion<br />

mit return this enden.<br />

Objektinstanzen aus einer gemeinsamen<br />

Definition entstehen<br />

also in Javascript durch den Aufruf<br />

new Funktion(Parameter). Innerhalb<br />

der in Funktionsvariable gespeicherten<br />

Funktion verhalten<br />

sich Variablen wie private Datenfelder<br />

oder – wenn ihr Inhalt eine<br />

Funktion ist – wie private Methoden.<br />

Dagegen erzeugt this.Attributname<br />

öffentlich zugängliche<br />

Attribute oder Methoden.<br />

Schwieriges Erbe<br />

Stellen Sie sich vor, Sie haben<br />

eine Klasse mit fünf Methoden<br />

definiert und möchten nun eine<br />

neue Klasse bilden, die vier davon<br />

übernimmt, die fünfte aber verändert:<br />

Ein klarer Fall für Vererbung.<br />

Wie das in Javascript geht,<br />

demonstriert Listing 3. Darin erhält<br />

die von Greeter() abgeleitete<br />

Klasse den bairischen Gruß.<br />

Der Code definiert die zwei<br />

Funktionen Greeter und extended-<br />

Greeter. In Greeter haben wir im<br />

Vergleich zur früheren Version<br />

toGreet in ein öffentliches Attribut<br />

verwandelt. extendedGreeter()<br />

definiert eine Methode bavarian-<br />

Hello(). Sie greift dabei auf das in<br />

Greeter definierte Attribut toGreet<br />

zu. Das funktioniert, weil die erste<br />

Zeile nach den Funktionsdefinitionen<br />

Greeter und extendedGreeter<br />

kombiniert. Diese Zeile bindet<br />

eine Instanz von Greeter an das<br />

prototype-Attribut der Definition<br />

von extendedGreeter.<br />

Alle Javascript-Objekte enthalten<br />

ohne explizite Definition ein<br />

prototype-Attribut mit fester Aufgabe:<br />

Alle mit new extendedGreeter()<br />

erzeugten Instanzen erben<br />

die Attribute des an prototype gebundenen<br />

Objekts.<br />

Allerdings gilt dies nur für die<br />

öffentlichen, mit this.Attributname<br />

definierten Attribute. Darum gilt<br />

es die Klasse Greeter zu verändern,<br />

um diese zu erweitern. Abbildung<br />

D zeigt einen Object-<br />

Dump der Firebug-Konsole mit<br />

der geerbten Methode sayHello()<br />

sowie dem neu hinzugefügten<br />

bava rianHello().<br />

Kollateralschaden<br />

Ein Vererben privater Attribute<br />

funktioniert in Javascript nur<br />

über Umwege – mit unterschiedlichen<br />

Auswirkungen auf die Performance<br />

([9],[10]). Dass keine<br />

Kombination der beiden mächtigsten<br />

Features – dem Erzeugen<br />

von Objektinstanzen mit new und<br />

einer Closure sowie dem Vererben<br />

auf Basis des Prototype-Attributs<br />

– möglich ist, hat der Sprache viel<br />

Kritik eingebracht. Die Objektorientierung<br />

in Javascript wirkt unausgegoren.<br />

Sie ist, wie viele Webstandards,<br />

vom Browser-Krieg<br />

zwischen Netscape und Microsoft<br />

gezeichnet. (agr) n<br />

D Ein Dump des<br />

Objekts greeter3 in<br />

der Firebug-Konsole<br />

(zweite, grüne Zeile<br />

links) zeigt, dass das<br />

Vererben aus dem Beispiel<br />

funktioniert: Das<br />

Objekt enthält das<br />

Attribut toGreet sowie<br />

die beiden Methoden<br />

bavarianHello() und<br />

sayHello().<br />

INFO<br />

[1] Programmiersprachen-Shootout: http:// shootout. alioth. debian. org/ u32/ which-p<br />

rogramming-languages-are-fastest. php<br />

[2] Javascript-Überblick: http:// www. w3schools. com/ js/ default. asp<br />

[3] JQuery: http:// jquery. com<br />

[4] Cascading Style Sheets (CSS):<br />

http:// de. wikipedia. org/ wiki/ Cascading_Style_Sheets<br />

[5] Selektoren: http:// api. jquery. com/ category/ selectors/<br />

[6] Traversing: http:// api. jquery. com/ category/ traversing/<br />

[7] Event Object: http:// api. jquery. com/ category/ events/ event-object/<br />

[8] Firebug: https:// addons. mozilla. org/ de/ firefox/ addon/ firebug/<br />

[9] Power Constructor: http:// www. crockford. com/ javascript/ inheritance. html<br />

[10] Closure-basierte Vererbung: http:// www. ruzee. com/ blog/ 2008/ 12/ javascript-in<br />

heritance-via-prototypes-and-closures<br />

www.linux-user.de<br />

11 | 12 29

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!