JavaScipt-Code
20. Juni 2014 von & 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.

über den Autor

krone@pluspol.info'
Stefan ist leidenschaftlicher Gamer, Film- sowie Musikliebhaber und begeisterter Entwickler. Sein Interesse gilt den neuesten Technologien. Seine stete Unzufriedenheit mit dem Status Quo treibt ihn an, besser zu werden.



Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.