13. Juli 2017 | | gespeichert unter Coding, Programmierung.

Viele haben sich bereits davon verabschiedet, aber für den ein oder anderen ist TemplaVoilà! für moderne TYPO3-Installationen nach wie vor nötig, wenn beispielsweise der Website-Relaunch in den Sternen steht oder eine Migration hin zu anderen Bibliotheken zu aufwändig ist.

Was ist TemplaVoilà!?

TemplaVoilà! ist eine beliebte Template-Extension, die es Nutzern ermöglicht, fernab der traditionellen Spalten- und Zeilenlayouts Inhalte ansprechend darzustellen. Im April 2006 wurde Version 1.0.0 veröffentlicht und bis heute über 380.000 Mal heruntergeladen.

Voilà, TemplaVoilà! Plus

Mit TemplaVoilà! 2.0.x gab es bereits einen Versuch, die Extension für TYPO3 7 LTS fit zu machen, jedoch fehlte es an Funktionen und der Zukunftssicherheit für TYPO3 8 LTS. Benjamin Mack leistete hier 2016 bereits gute Vorarbeit.

So haben wir bei PLUSPOL interactive uns daran gesetzt, dem guten alten TemplaVoilà! einen zweiten Frühling zu bescheren. Von September bis Dezember 2016 entwickelten wir die überarbeitete Extension, die nun vollständig zu aktuellen TYPO3-Versionen kompatibel ist. Die nötigen Änderungen wurden mit kommentierten Commits auf GitHub veröffentlicht. Diverse Demosysteme mit Echtdaten dienten uns als Testplattformen, wobei wir auch weitergehende Features wie Mehrsprachigkeit und Workspaces prüften.

Nachdem wir auch kleinere Probleme der ersten Nutzer gefixt hatten, machten wir uns daran, ein Paket zu schnüren und dies im TYPO3 Extension Repository (TER) zu veröffentlichen. Leider war es uns nicht möglich, die Extension unter dem gleichen Namen bereitzustellen, weshalb wir uns gezwungen sahen, dem Kind einen neuen Namen zu geben. Damit einher ging die Entwicklung umfangreicher Migrationsskripte, um den Umstieg für alle Nutzer so leicht wie möglich zu gestalten.

Am 13. März 2017 erblickte unser neues TemplaVoilà! Plus in Version 7.0.0 das Licht der TYPO3-Welt und hat seitdem fleißig Erweiterungen und Schönheitskorrekturen erfahren, sodass wir am 05. Juli 2017 bereits die Version 7.1.2 veröffentlicht haben. Mehr als 570 Downloads aus dem TER zeigen uns, dass die Extension auch in Zukunft eine Rolle im TYPO3-Universum spielt.

Wie zukunftssicher ist TemplaVoilà! Plus?

TemplaVoilà! Plus ist kompatibel zu TYPO3 7/8 LTS, wodurch eine Lauffähigkeit für die nächsten 3 Jahre gegeben ist. Zudem entwickeln wir die Extension aktiv weiter. So wollen wir das Mapping modernisieren und den Sourcecode aufräumen, da auch dort die Spuren der Zeit zu erkennen sind. Ebenso streben wir eine Kompatibilität zu TYPO3 9 LTS an.

Wie aufwändig ist die Migration von TemplaVoilà! zu TemplaVoilà! Plus?

Um auf TemplaVoilà! Plus umzusteigen, sind einige einfache Schritte notwendig. Voraussetzung ist ein installiertes TemplaVoilà! 1.8, 1.9 oder 2.0.

  • Ein Backup aller Daten (Datenbank und Dateien) sollte wie bei jedem Upgrade angefertigt werden.
  • Das Update von TYPO3 6.2 LTS auf TYPO3 7 LTS (oder auch gleich TYPO3 8 LTS) kann wie üblich vorgenommen werden.

 

  1. Die bisherige TemplaVoilà!-Extension deaktivieren.
  2. TemplaVoilà! Plus im ExtensionManager aus dem TYPO3 Extension Repository (TER) installieren und aktivieren.
  3. Im ExtensionManager den „Update“ Button der TemplaVoilà! Plus Extension betätigen.
  4. „Migrate TemplaVoilà! 1.8/1.9/2.0“ anklicken und den Start der Migration bestätigen.
  5. Nun einen Moment warten, bis alles nach TemplaVoilà! Plus migriert wurde, von den Einstellungen bis hin zu den Templates. Selbst die Icons oder Static Data Structures werden übernommen. Allein das TypoScript muss im Nachgang händisch angepasst werden.
  6. Nach Abschluss der Migration müssen noch die DataStructures den TCA Änderungen von TYPO3 7/8 angepasst werden. Dies geschieht über die Funktion „Update DataStructure from TYPO3 6.2 to 7/8 LTS“. Dieser Task besitzt eine eigene Versionsnummer und wird nach wie vor erweitert und angepasst. Er kann somit regelmäßig nach dem Aktualisieren von TemplaVoilà! Plus ausgeführt werden.
  7. Was nun noch bleibt, ist die manuelle Anpassung des TypoScript. Dabei müssen alle Vorkommen von tx_templavoila zu tx_templavoilaplus abgeändert werden. Wer möchte, kann dabei gleich seine TypoScripts aufräumen. 😉 Das PAGE Objekt sollte anschließend wie folgt aussehen:

Alles erledigt? Dann Trommelwirbel und schauen, was das Frontend dazu sagt. Wir drücken auf jeden Fall die Daumen, dass auch Ihr System einwandfrei funktioniert.

Sollte doch etwas schief laufen oder Fragen auftauchen, so stehen wir und andere User gerne im Slack Channel oder auf GitHub zur Verfügung.

Weitere Links:

10. August 2016 | | gespeichert unter Coding, Programmierung.

Ihr habt es ja wahrscheinlich schon mitbekommen: Unser Entwickler Florian hat einen gut besuchten Vortrag an der HTWK Leipzig gehalten und gezeigt, wie ein moderner Webentwicklungs-Workflow funktioniert.

Falls ihr nicht dabei sein konntet, euch aber brennend dafür interessiert, wie ihr CSS-Dateien mit Autoprefixer verarbeitet oder JS-Features mit Babel kompiliert: Schaut doch einfach mal bei Slideshare vorbei, wir haben euch die Folien online gestellt. Viel Spaß beim Durchklicken! Weiterlesen »

16. Januar 2015 | | gespeichert unter Coding, Programmierung.

Noch etwa zur Zeit, als Apple seine ersten Entwicklerwerkzeuge für das iPhone veröffentlichte oder als Google mit Android daherkam, war es relativ schwer vorstellbar, HTML, CSS und JavaScript für die Entwicklung von Apps zu nutzen. Zu schwach war noch die Hardware oder zumindest der interne Browser. Doch das hat sich mittlerweile enorm gewandelt. Weiterlesen »

8. August 2014 | | gespeichert unter Coding.

Closures war das bestimmende Thema meines vorherigen Blog-Posts, in dem ich die Vorzüge der Funktion als ein Objekt höherer Ordnung darstellte. Der Quellcode kann dadurch schlanker sein und auch die Kapselung von Klassen geht damit leicht von der Hand. Teil drei, und damit der letzte Teil in meiner Reihe (hier ist Teil 1 und Teil 2) über die JavaScript-Funktion, beschäftigt sich diesmal mit vollmundigen Versprechungen: den Promises (oder auch Futures). Grob zusammengefasst ist ein Promise ein Wrapper, der möglicherweise erst in der Zukunft einen Wert enthält. Aber warum möchte man das und wie funktioniert das?

Aus der Callback-Hölle

JavaScript hat ein recht simples Ausführungsmodel, alles hört auf den Event-Loop, der i.d.R. bis zu 60 mal pro Sekunde ausgeführt wird, und dieser läuft in einem einzigen Thread. Daraus resultiert natürlich, dass nebenläufige oder parallele Prozesse nicht ohne Weiteres möglich sind.1 Das ist auch gar nicht notwendig, denn JavaScript arbeitet im Bezug auf Input/Output nicht-blockierend. Das heißt, dass Event-Handler sowohl den Input als auch die Resultate des Outputs behandeln. Sende ich also eine Ajax-Anfrage mit jQuery, unterbricht die Ausführung nicht und geht erst mit dem Ergebnis der Anfrage weiter, sondern ich muss ein Callback angeben, das die Antwort entgegennimmt. In der Zwischenzeit kann also ganz anderer Code ausgeführt werden, das Ganze läuft also asynchron.

So toll das auch sein mag, hat das einen entscheidenden Nachteil: Sind mehrere aufeinanderfolgende asynchrone Anfragen notwendig, verschachteln sich die Callbacks gerne mal sehr tief. Das mindert die Lesbarkeit des Quelltextes und erhöht durchaus auch Fehler aufgrund der unterschiedlichen Bindungen der einzelnen Closures (siehe nochmals den vorangegangenen Blog-Post). So etwas wird auch als Callback-Hell bezeichnet. Das folgende Code-Listing zeigt das einmal beispielhaft mit der Facebook-API:

So, oder so ähnlich, kann ein Code-Schnipsel für eine Facebook-App aussehen. Leider ist das Konstrukt nicht leicht zu lesen und zusätzlich gibt es mehrere Stellen, die die gleiche Funktionalität fordern. Wie kann man das also verbessern? Eine Lösung ist, eine Sequenzierung einzuführen. Und in diesem Fall kommen Promises ins Spiel. Dazu empfiehlt sich z.B. die q-promises-Bibliothek. Die README sowie das Wiki des Projekts bieten einen sehr guten Einstieg.

Von vollmundigen Versprechungen

Soll eine asynchrone Aktion durchgeführt werden, wird zunächst ein sogenanntes „Deferred Object“ (engl. aufgeschobenes Objekt) erzeugt. Dieses enthält das letztendliche Promise und zwei wesentliche Funktionen: resolve( value ) und reject( reason ). Sobald der Browser die entsprechenden Events sendet, kann die entsprechende Antwort an das „Deferred“ weitergeleitet werden. Bei einer positiven Antwort, wird die resolve-Methode mit der Antwort als Wert aufgerufen, bei einer negativen Antwort wird die reject-Methode mit dem Fehler bzw. einer Fehlerbeschreibung als String aufgerufen. Das Promise-Objekt hat im Wesentlichen die then-Methode (promise.then( onResolved, onRejected, onNotified)). Diese wird mit bis zu drei Callbacks als Argumente aufgerufen und gibt jeweils wiederum immer ein Promise-Objekt zurück. Dadurch lassen sich Aktionen bequem verketten. Der erste Callback (onResolved) soll ein positives Ergebnis des asynchronen Aufrufs entgegennehmen. Der zweite Callback (onRejected) wird bei einem negativen Ergebnis ausgeführt. Der letzte Callback (onNotified) ist der einzige, der mehrfach aufgerufen werden kann. Dadurch kann man z.B. den Fortschritt bei einem Datei-Upload abbilden. Nun aber ein Code-Beispiel:

Die Arbeit mit dem „Deferred Object“ kann man sich dank der q-Bibliothek auch ersparen, da sie jQuery-Ajax-Requests entsprechend behandeln kann. Die ajax-Methode von jQuery gibt ebenfalls Promises zurückgeben, nur sind diese nicht ganz so mächtig. Ein Video beleuchtet den Unterschied genauer, weshalb ich hier nicht näher darauf eingehen werde. Wie kann man also unsere request-Funktion kürzer schreiben:

Das ist doch gar nicht schlecht, oder? Wir überlassen es der q-Bibliothek, wie sie den Ajax-Request auswertet und kümmern uns nur noch um die Handler-Funktionen. Wichtig dabei: Die Rückgabewerte der Handler werden unverändert an den nächsten Handler weitergegeben, sofern sie selbst kein Promise sind. Gehen wir nun den entscheidenden Schritt weiter und schauen uns an, wie wir unseren Facebook-Code aufräumen und übersichtlicher gestalten können. Zunächst brauchen wir sogenannte Wrapper-Funktionen, die die Aufrufe der Facebook-Methoden in Promises umwandeln:

Das mag zwar deutlich mehr Code sein als noch im Eingangs-Beispiel, der Vorteil ist nun aber, dass die Angabe eines Callbacks nicht mehr benötigt wird und jede Funktion sofort ein Promise zurückgibt. Nun soll natürlich nicht die Implementierung der Sequenzierung unserer Facebook-Anfrage fehlen:

Das sieht doch gleich viel aufgeräumter aus, oder? Wir haben einen klaren und leicht lesbaren Kontrollfluss und doppelte Aufrufe werden vermieden. Der Quelltext ist somit leichter wartbar und ein neuer Entwickler kann sich recht schnell zurechtfinden.

Zusätzlich sind einige Schmankerl der q-promises enthalten. So weiß die Bibliothek, wie es mit den Rückgabe-Werten umgehen soll. Im ersten then-Handler sind im if-else-Statement drei entsprechende Fälle zu sehen. Fall eins gibt normal das Argument zurück, die q-Bibliothek reicht dieses an den nächsten Handler weiter. Fall zwei wirft einen Fehler, dieser wird von der q-Bibliothek abgefangen und an den nächstmöglichen Fehler-Handler weitergeleitet. In diesem Fall würden sämtliche anderen Handler ignoriert und komplett zur onError-Funktion gesprungen. Diese wird dann mit dem geworfenen Fehler als Argument aufgerufen. Der Fehler kann abgefangen werden und eine völlig andere Sequenz von Aktionen zur Folge haben. Der dritte Fall gibt ein neues Promise-Objekt zurück, dessen Sequenz die q-Bibliothek erst abarbeitet, bevor sie die übergeordnete Sequenz weiterverfolgt.

Was wir hier bisher sehen, sind nur ein paar Aspekte von Promises. Sie sind noch weitaus vielfältiger und ein Blick in die Dokumentation lohnt sich. Sie sind auch ein weiteres Beispiel für die Vielseitigkeit der JavaScript-Funktion und eine Brücke hin zur funktionalen Programmierung, in der Konstrukte wie Promises ein wesentlicher Bestandteil sind.

Persönlich habe ich Promises schon lange im Einsatz. Nutzt ihr sie ebenfalls? Was sind eure Erfahrungen? Oder habt ihr vielleicht andere oder gar bessere Ansätze? Berichtet mir von euren Erfahrungen.

Damit schließe ich meine Artikel-Reihe zur JavaScript-Funktion. Ich hoffe, es hat euch gefallen und ihr konntet neue Inspiration für eure tägliche Arbeit daraus ziehen. Bei Kritik und Anregungen schreibt einfach einen Kommentar. Derweil werde ich meine magische Kugel nach den nächsten Themen befragen. Bis dahin: Stay tuned!


  1. Die sogenannente Web-Worker sind eine Möglichkeit, Code außerhalb des Event-Loops ausführen zu lassen

25. Juli 2014 | | gespeichert unter Coding.

One Pager erfreuen sich im Netz wachsender Beliebtheit, wie unser Neuer für Rügenwalder Mühle, den wir nach einem Konzept von elbkind umgesetzt haben. Dank HTML5 und CSS bietet die einzelne Seite eine schicke Bühne, um eine Marketing-Aktion von Rügenwalder zu präsentieren – und zwar gleichermaßen auf Desktop, Tablet und Smartphone (Stichwort: responsive Design).

Die Erfahrungen, die unsere Entwickler bei diesem Projekt gesammelt haben, teilen wir heute in 5 Tipps mit Euch:

1. Lazy Loading

Was zuerst nicht nach Optimierung klingt (lazy?), ist eben das. Grafiken, JavaScript und CSS Dateien etc. werden bei Bedarf geladen, sprich wenn eine Aktion von Nutzer oder Software ausgeführt wird. Bei Toughmühle löst das Scrollen des Nutzers das Nachladen aus.

2. CSS statt Grafiken

Jede Grafik auf einer Website hat einen lähmenden Einfluss auf die Ladezeit. Ein Killer vor allem für die mobile Darstellung. Damit das nicht passiert, haben wir so viel wie möglich in CSS-Code gepackt. Der Hover-Effekt in der Fotogalerie ist z.B. mit CSS realisiert. Früher hätte man an der Stelle zwei Bilder hinterlegt – ein schwarz-weißes und ein buntes – und bei Mouse-over entsprechend miteinander vertauscht.

toughmühle_slider



Heute erzielt dieser CSS-Code denselben Effekt und spart dabei Ressourcen:

3. Serveranfragen minimieren

Zu diesem Zweck haben wir JavaScript- und CSS-Dateien mit Grunt zu einer Datei zusammengefasst. Auch die Icons im Footer liegen nicht in mehreren Dateien vor, sondern gebündelt in einer sogenannten Spritegrafik – statt vieler Bilder lädt die Seite nur eins. Und das dann eben schnell.

toughmühle_footer

4. Ladezeiten reduzieren

Wie oben bereits erwähnt: Bilder lähmen. Der One Pager für Toughmühle strotzt nur so vor Illustrationen und Fotos. Mit smushit haben wir diese nochmals komprimiert. Das intelligente Tool entfernt Informationen aus der Datei, die das menschliche Auge ohnehin nicht wahrnimmt.

5. Reichweite erhöhen

Dank responsive Design kann ein One Pager auf einer Vielfalt von Geräten optimal dargestellt und genutzt werden. Um den Programmieraufwand zu reduzieren, haben wir aufBootstrap gesetzt. Das Open Source Framework liefert responsive Templates, die sich an die eigenen Wünsche anpassen lassen.

Über das Projekt:

Ein Team von Rügenwalder Mühle stellt sich dem Toughmudder Hindernis-Lauf. Bilder und Videos der Trainings und des Laufs gibt es auf dem One Pager zu sehen. Zusätzlich ist die Seite noch auf Facebook und Youtube eingebunden. Um das Projekt schlank zu halten, ist die Seite statisch und ohne dahinterliegendes CMS realisiert. Idee und Konzept stammen von elbkind, das Design von Rügenwalder Mühle selbst.

Folgende Technologien und Funktionen kommen zum Einsatz:

  • HTML5
  • Responsive Design
  • JSON konfigurierbare Slider mit Swipe-Funktion
  • Modal Overlay für die Bilder
  • CSS3 Keyframe Intro Animation
  • Countdown Funktionalität

18. Juli 2014 | | gespeichert unter Coding.

Im vorangegangenen Blog-Post zur JavaScript-Funktion habe ich einige Grundlagen zum Funktions-Objekt in JavaScript etabliert. Ich demonstrierte in kleinen Beispielen die Vielseitigkeit und schloss den Artikel mit Beispielen für eine simple objektorientierte Programmierung in JavaScript. Wer sich mit fortgeschrittenen Methoden beschäftigen mag, dem seien Bibliotheken wie Klass, Classy oder FastClass sowie andere, in JavaScript kompilierende Programmiersprachen wie CoffeeScript oder TypeScript empfohlen. Teil 2 beschäftigt sich nun mit Closures.

Ein Closure ist ein geläufiges Konstrukt für jeden JavaScript-Entwickler, eine erste Berührung damit hat jeder Anfänger mit den Event-Handlern, z.B. für Maus-Ereignisse (onclick u.a.). Event-Handler werden meist als anonyme Funktionen übergeben, wobei Closures nicht zwangsläufig anonym sein müssen. Die wichtigere Eigenschaft ist aber, dass sie den Kontext ihrer Erstellung behalten und nutzen können. Ein kleines Beispiel soll das verständlich machen:

Unser kleiner Währungsrechner im Beispiel ist eine einfache Implementierung mit Hilfe eines Closures. Die Funktion getConcurrenyConverter gibt eine neue Funktion zurück, die ihre Umgebung an sich bindet. Diese Umgebung ist der Wert von x. Die zwei Anwendungen für dollar2euro sowie euro2dollar verdeutlichen das, in dem sie mit den korrekten Umrechnungswerten erzeugt wurden. Dieses kleine Beispiel verdeutlicht schon sehr gut, wie mächtig Closures sein können. Um ein wenig Theorie einzuwerfen: in unserem Beispiel ist getConcurrenyConverter eine Funktion höherer Ordnung, da sie eine neue Funktion zurückliefert. Das ist möglich, da Funktionen in JavaScript sogenannte „First-Class-Objekte“ sind, sie also wie jedes andere Objekt (Zahlen, Strings, Arrays, Objekte) als Argument oder Rückgabewert einer Funktion genutzt oder auch einfach in einer Variable abgelegt werden können.

Weniger Code

Closures können auch zu einer saubereren Code-Basis führen. So muss man temporäre Werte nicht unbedingt global vorhalten, sondern kann sie auch in einem Closure binden. Ein schönes Beispiel dazu wäre ein Drag&Drop mit jQuery für ein HTML-Element:

Dieses Beispiel ist schon ein wenig umfangreicher, aber die ganze Magie befindet sich eigentlich nur in der Funktion getDragHandler(). Zum Ausprobieren reicht es lediglich, die Website http://jquery.com/ aufzurufen und den Code in der Webkonsole auszuführen. Klickt man nun auf das jQuery-Logo, lässt es sich bei gedrückter Maustaste umherbewegen. Herzlichen Glückwunsch, ein erstes interaktives Beispiel für Closures!

OOP-Closures

Dank der Dynamik und Vielseitigkeit von JavaScript lassen sich auch Closures bzw. deren Eigenschaften auf andere Aspekte übertragen, z.B. der objektorientierten Programmierung. Persönlich bin ich kein großer Fan der prototypischen Vererbung (also über Klasse.prototype). Ein großer Nachteil ist das Fehlen privater, also nach außen nicht sichtbarer Eigenschaften und Funktionen. Da ich auch nicht extra eine weitere Bibliothek in meine Projekte einbinden möchte, greife ich gerne auf eine zweite Form der Vererbung zu. Dazu ein Beispiel:

Das ist natürlich jetzt ein deutlich umfangreicheres Beispiel1, aber es zeigt eine schöne und gut funktionierende Struktur. Zunächst wird die Klasse in eine Funktion eingehüllt, die nur meine Klasse zurückliefert. Alles andere bleibt für die äußere Umgebung unsichtbar. Die Variable STATIC_OPTION ist z.B. nur innerhalb der Hüllenfunktion sichtbar, sie ist also privat. Das Gleiche gilt für die innere Klasse Item. Die eigentliche Klasse LinkedList enthält auch einige Schmankerl. Zunächst binde ich den this-Kontext an die (private) Variable self.2 Genauso wie die nachfolgenden Variablen3 sowie Funktionen ist diese Variable privat. Erst die an self gebundenen Funktionen und Variablen sind öffentlich. Nach der Deklaration der Klasse, binde ich noch statische Variablen an ihr. Diese sind öffentlich, weil sie gemeinsam mit der Klasse exportiert werden. Ich hoffe, die Kommentare helfen beim Verstehen der unterschiedlichen Kapselungen.

Was hat das nun aber mit Closures zu tun? Nun ja, ganz einfach: dieses Beispiel ist eine gebündelte Struktur von Closures. Die zurückgegebene Klasse LinkedList ist eine Closure, die ihre Umgebung innerhalb der Hüllenfunktion an sich bindet, z.B. STATIC_OPTION bzw. die innere Klasse Item. Zusätzlich ist jede öffentliche Methode einer Instanz (new LinkedList) eine Closure ihrer Umgebung. In diesem Fall zählen dazu noch die privaten Variablen und Methoden der Instanz.

Das ist mein Ansatz zur Strukturierung meiner JavaScript-Klassen in Projekten. Wie ist Eurer? Arbeitet Ihr viel mit Closures? Welche Erfahrungen habt Ihr gemacht?

Im nächsten Blogpost möchte ich das Thema der Callbacks angehen und über eine wundervolle Möglichkeit schreiben, diese besser zu strukturieren. Bis dahin: Stay tuned!


  1. das zwar unvollständig ist, aber so im Browser oder in Node.JS ausprobiert werden kann
  2. Ich referenziere den this-Kontext mit self, weil ich dadurch einigen Problemen von JavaScript aus dem Weg gehen möchte. Jede Funktion wird mit einem this-Kontext aufgerufen, quasi ein zusätzliches Argument, das der Funktion automatisch übergeben wird. Das Problem sind die Callbacks, wie sie z.B. bei Ajax-Requests genutzt werden. Der this-Kontext der Callback-Funktion muss nicht zwangsläufig der von mir erwartete sein, oftmals ist er ein anderer. Das führt zu schwer auffindbaren Fehlern. Es gibt zwar andere Möglichkeiten, dieses Problem zu lösen. Aber durch meine durchgängige Nutzung der self-Variable gehe ich immer sicher, dass ich im richtigen Kontext arbeite.
  3. Übrigens, der Unterstrich an den Variablen _size oder _head soll auch optisch verdeutlichen, dass es eine private Variable ist. In einer Entwicklungsumgebung mit Auto-Vervollständigung ist es dadurch meist angenehmer, auf diese zuzugreifen

20. Juni 2014 | | gespeichert unter Coding.

JavaScript hat in den letzten Jahren einen enormen Aufwind bekommen. Unzählige Frameworks und Bibliotheken sprießen aus dem Boden und bereichern uns in der Webentwicklung mit allerhand Bequemlichkeiten. jQuery hilft uns mit DOM-Manipulationen und Ajax-Requests, Ember oder AngularJS vereinfachen das Entwickeln skalierbarer Web-Applikationen, underscore oder Lo-Dash unterstützen uns bei der Arbeit mit Listen und anderen Datentypen. All das wird begünstigt durch das Programmierkonstrukt der Funktion. Was macht die JavaScript-Funktion also so besonders?

Die Basics

In der Mathematik entspricht die Funktion der Abbildung einer Menge von Objekten auf eine neue Menge von Objekten. Ist das bei JavaScript anders? Sie muss nicht zwangsläufig etwas zurückgeben. In diesem Fall spricht man meist von Prozeduren. Ist die Funktion an ein Objekt gebunden (z.B. Math.sin()) spricht man von einer Methode. In jedem Fall kann die Anzahl der übergebenen Argumente beliebig sein. Probieren wir es doch gleich mal aus (alle Beispiele können mit der Konsole im Browser oder auf der Kommandozeile mit Node.js getestet werden.):

Gehen wir einen Schritt weiter. JavaScript ist durchaus eine vollwertige Programmiersprache, auch wenn das nicht jeder so sehen mag:

JavaScript ist objektorientiert

Die objektorientierte Programmierung ist eine der wesentlichen Prinzipien in der Entwicklung von Software-Systemen. Sie hilft, Aspekte und Programmteile zu strukturieren und die Entwicklung effizienter zu gestalten. Ein wichtiges Konzept ist das der Klassen. Für einen Aspekt (z.B. ein User-Objekt) schreibe ich also eine Klasse, welche ich in Zukunft ganz einfach wiederverwenden kann. Java und C++ sind dafür wohl die bekanntesten Beispiele aus der Lehre. Bei JavaScript spricht man von „objektbasiert“. Ohne wirklich auf die Unterschiede einzugehen, sei nur gesagt, dass JavaScript an sich keine Klassen kennt.1 Diese können aber dank des flexiblen Objekt-Modells nachgebildet werden:

Grundlegend ist die Funktion in diesem Fall ein sogenannter Konstruktor. Wird er mit dem Schlüsselwort new vorangestellt, erzeugt (konstruiert) die Funktion ein neues Objekt. In objektorientierten Sprachen kann ich eine neue Klasse erzeugen, die ihre Eigenschaften von einer anderen erbt. Dafür bietet JavaScript zwei sehr einfache Wege:

Die erste Variante nutzt das sogenannte Prototyping.2 Jede Funktion hat eine Eigenschaft prototype, die mit jedem beliebigen Objekt versehen werden kann. In diesem Fall wird dem prototypevon Snake ein neues Objekt Animal angehängt. Dadurch erbt Snake automatisch von Animal. Dass aber die Eigenschaft kind den Wert snake hat, liegt an der sogenannten Prototype-Chain. JavaScript hangelt sich auf der Suche nach dem Wert einer Eigenschaft durch diese Kette, bis ein Prototype-Objekt gefunden wurde, das eine solche Eigenschaft enthält. In der letzten Zeile ist name undefined, da der Animal-Instanz kein Wert dafür übergeben wurde.

Nun die zweite Möglichkeit:

Auffällig ist die erste Zeile unseres Konstruktors: Hier wird Animal aufgerufen, aber anders als vielleicht erwartet. Dazu sei erwähnt, dass jede Funktion neben der prototype-Eigenschaft auch zwei Funktionen call() und apply() besitzt. Auf die Unterschiede möchte ich im Moment nicht eingehen.3 Es sei lediglich erwähnt, dass sie die Funktion dazu bewegen, auf ein spezifisches Objekt (in diesem Fall this) angewandt zu werden.

Der Unterschied zum vorangegangenen Beispiel ist jeweils in der letzten Zeile der Code-Schnipsel ersichtlich. Während die prototype-Variante dort ein Animal-Objekt zurückliefert, ist das in Variante zwei nicht der Fall. Im letzten Beispiel wird die Vererbung händisch mit jedem Aufruf des Konstruktors vollzogen. Das kommt später zum Tragen, wenn man in den Konstruktoren sogenannte private4 Eigenschaften einführt. Gleichzeitig wird dadurch verhindert, dass die Prototype-Chain durchlaufen wird, was durchaus einen minimalen Performance-Gewinn bedeuten kann, wobei dann aber die Erzeugung des neuen Objekts kostspieliger ist.

Das soll’s erst einmal dazu gewesen sein. Im zweiten Teil beleuchte ich den Einsatz von Funktionen als Closures/Callbacks und gehe auf die sogenannten Promises ein. Stay tuned!

Nutzt Ihr auch Klassen in Euren Projekten? Schreibt uns dazu einen Kommentar.


  1. noch nicht
  2. Prototypenbasierte Programmierung
  3. call() erwartet zu allererst den this-Kontext und dann kommasepariert die weiteren Funktionsargumente (fun.call(this, arg1, arg2, ...)). apply() jedoch erwartet nach dem this-Kontext eine Liste von Argumenten (fun.apply(this, [arg1, arg2, ...])).
  4. Eigenschaften, die nur innerhalb des erzeugten Objekts verfügbar sind, aber nicht außerhalb. Private Variablen dienen der Kapselung, interne Logik wird nach außen nicht freigegeben.