Objektorientiertes JavaScript – Kapitel 1

By | 22. Juli 2012

Objektorientiertes JavaScript? Objektorientierte Programmierung (OOP) hier, OOP da … überall OOP. Wer in den letzten paar Jahren erst begonnen hat sich mit der Programmierung auseinander zu setzen, wird mit hoher Wahrscheinlichkeit mit einer objektorientierten Programmiersprache wie C++ oder Java angefangen haben. Anders sieht das aus, wenn man mit einer imperativen Sprache wie C eingestiegen ist. Oft fällt der Umstieg in die Denkensweise der OOP schwer, da man die verschiedenen Prinzipien erstmal verstehen muss. JavaScript selbst, obwohl klassenlos, ist eine … ich sage mal „Allround Skriptsprache“, mit der wir auch objektorientiert arbeiten können. Nicht umsonst hat Douglas Crockford geschrieben:

JavaScript: The World’s most misunderstood programming language.

Heute möchte ich gern zeigen, wie man das Klassenprinzip ins JavaScript portieren kann. Dazu baue ich eine Klasse mit privaten und öffentlichen (bzw. privilegierten) Variablen und Methoden und zeige die verschiedenen Zugriffsarten. Los geht’s …

Die Klassenstruktur

Die Klasse hat folgende Grundstruktur:

Der Konstruktor

Natürlich wird ein Konstruktor benötigt um Objekte zu erstellen – sagt ja schon der Name. Also wird so einer erstellt. Dabei sollten ein paar Dinge beachtet werden:

  • Konvention: obwohl grunsätzlich eine Camel Case Schreibweise bevorzugt wird, sollte der erste Buchstabe des Konstruktors großgeschrieben werden
  • Parameter: die dem Konstruktor übergebenen Parameter sind grundsätzlich private Variablen

Unser Troll-Konstruktor hat genau zwei Parameter, mit der der Name  und die Gesinnung (attitude) gesetzt werden kann, wenn das Objekt erstellt wird. Ein neues Objekt wird – ähnlich wie in Java – mit dem Schlüsselwort newerstellt, gefolgt vom Konstruktornamen mit Klammern (und eventuellen Parametern). Die Sichtbarkeit der einzelnen Variablen (und später auch Methoden) ergibt sich immer aus dem selben Schema…

Sichtbarkeiten private, privilegiert

Theoretisch gibt’s drei Sichtbarkeiten (Scopes):

privat (private)

  • Eigenschaften: sind nur innerhalb des Objekts sichtbar, kein Zugriff von Außen sondern ausschließlich über private oder privilegierte Methoden
  • Variablen & Methoden: Parameter des Konstruktors und Variablen, welche innerhalb des Konstruktors mit var deklariert werden
  • hier: das Objekt privateVars

privilegiert (privileged)

  • Eigenschaften: sind von außen sichtbar und können auf private Variablen und Methoden zugreifen
  • Variablen & Methoden: alle die mit dem this-Schlüsselwort deklariert werden
  • hier: die attitude-Variable

öffentlich (public)

  • Eigenschaften: können von außen erreicht werden, haben keinen direkten Zugriff auf private Variablen, werden über die prototype-Eigenschaft des Konstruktors erstellt
  • dazu weiter unten mehr

Damit kann sehr schön das Klassenkonzept aus „echten“ Programmiersprachen abbilden und sich austoben. Unser Beispiel Troll von oben hat also drei private Variablen: die Parameter name & attitude sowie das Objekt privateVars (ist ja mit var deklariert, damit privat). Die Variable this.attitude hat den privilegierten Scope.

Nun wollen wir aber mal noch ein paar Methoden einbauen …

Privilegierte Getter & Setter

Damit der Zugriff auf die privaten Variablen auch irgendwie möglich ist, habe ich vorhin schon von dem privilegierten Scope gesprochen. Erweitern wir also jetzt mal das Troll-Objekt jeweils um eine Methoden zum Setzen und eine Methode zum Holen des Namens…

Jetzt sind da zwei wirklich einfache Methoden, die es uns gestatten den Zugriff auf das private Objekt privateVars zu steuern. Dazu, denke ich, muss nicht mehr viel ausgeführt werden.

Öffentliche Methoden & Variablen

Gänzlich öffentliche Methoden sind natürlich auch realisierbar. Wie oben schon beschrieben, passiert das über die prototype-Eigenschaft. Damit wird die „Klasse“ im public Scope erweitert:

Die Ausgabe jetzt sollte ergeben: „Gustav ist gelangweilt“. Die öffentliche Methode getTrollInfo() greift als erstes auf die privilegierte Methode getName() zu um den Namen zu erfahren. Danach wird auf die privilegierte Variable attitude zugegriffen.

Zusammenfassung / Ausblick

Wir haben gesehen, wie das Zusammenspiel zwischen den verschiedenen Sichtbarkeitsbereichen aussieht. Die Möglichkeiten hier sind sehr vielfältig. Ein anderer Bestandteil der OOP ist die Vererbung. Auch das ist mit objektorientierten JavaScript grundsätzlich möglich. Wie genau das aussieht, werde ich in einem nächsten Kapitel erläutern.

Zugabe: Typenüberprüfung

JavaScript ist ja eine Skriptsprache mit dynamischer Typisierung. Das heißt, erst zur Laufzeit des Programms findet die Typzuweisung (String, Objekt, Number …) statt. Hat eine Variable keine Zuweisung, hat sie in der Regel den Wert undefined. Will man jetzt überprüfen, ob ein Parameter einen bestimmten Wert hat, kann man das mittels if-Anweisung checken. Sehr gut eignet sich dazu das typeof. Die Abfrage des typeof liefert den Typen des übergebenen Objekts zurück.

Nun gibt’s aber dabei teilweise ein paar Probleme. So ist z.B. der typeof-Wert eine Objekts natürlich object, aber auch object. Folgendes Beispiel demonstriert das:

Sichere Prüfung mittels constructor-Eigenschaft

Diese Falle kann man umgehen, in dem die constructor-Eigenschaft des jeweiligen Objekts überprüft wird. Dabei ist die Rückgabe die Funktion zur Erzeugung des jeweiligen Objekts (z.B. Object, Array, String …) . Das Beispiel von oben lässt sich damit sehr schön erweitern:

Dabei kann man sehen, dass myObj.constructor Object zurückliefert, wobei myArr.constructor Array besitzt. Somit kann man die eigentlichen zwei Objekte trotzdem unterscheiden. (constructor hat in modernen Browser noch das Attribute name, das hier verwendet werden kann)

2 thoughts on “Objektorientiertes JavaScript – Kapitel 1

  1. Ronny Deuse

    Spannender Artikel! Grade in Zeiten von AJAX und Fat Browser Clients wird es IMHO immer wichtiger, den JS Code etwas zu „disziplinieren“ um ihn wartbar zu halten. Das von Dir beschriebene Konzept privater Variablen mit dem var-Schlüsselwort in der Konstruktor-Methode war mir übrigens vollkommen neu. Ich hab das bisher über die _ und __ Konvention gelöst gehabt. Aber ich probier das gleich einmal aus! 🙂

    BTW: Prototype und Qooxdoo bringen direkt ein paar nette Hilfsfunktionen (Prototype) und ein komplettes Anwendungsgerüst (Qooxdoo) für OO JS Code mit. Unbedingt mal einen Blick darauf werfen!

  2. Benno Post author

    Hey Ronny,
    die Links sehen super aus und die werde ich definitiv auch mal anschauen und durchgehen. Danke dafür!
    Was ich dir auch noch ans Herz legen kann sind diese JS Design Pattern. Da kannst du dich noch tiefer einlesen 🙂

Schreibe einen Kommentar

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