Facebook
Twitter
Google+
Kommentare
22

Objektorientiertes JavaScript

Der erste Artikel dieser Art soll sich mit der objektorientierten Verwendung von Javascript beschäftigen – und ist für alle jene bestimmt die Javascript nur als nette kleine Ergänzung kennen, um z.B. beim Klick auf einen Button eine Fehlermeldung auszugeben.

In meinem ersten Artikel für „phphatesme.com“ soll es um die objektorientierten Ansätze von Javascript gehen. Der Artikel erhebt keinen Anspruch darauf, ein vollständigerer Guide für die objektorientierte Entwicklung mit Javascript in Webentwicklungen zu sein. Viel eher will ich euch zeigen, zu was Javascript alles fähig ist – und wo die Vorteile dieser Art von Entwicklung liegen.

Anfangen möchte ich gerne mit einem praktischen Beispiel. In PHP:

class MyWindow
{
	private $title = '';
	private $size = null;

	public function __construct($newTitle)
	{
		$this->title = $newTitle;
	}

	public function setSize($width, $height)
	{
		$this->size = array('width' => $width, 'height' => $height);
	}
}

Klassen in Javascript funktionieren so leider nicht. Javascript kennt weder die Keywords „public“ noch „private“ noch einen Konstruktor. Bevor ich euch jetzt weiter auf die Folter spanne, hier die gleiche Klasse – in Javascript:

function MyWindow(newTitle)
{
	var title = '';
	var size = null;

	this.setSize = function(width, height)
		{
			size = {width: width, height: height};
		}

	title = newTitle;
}

Und schon habt ihr es geschafft. Dem aufmerksamen Leser ist mit Sicherheit nicht entgangen, dass das erste Schlüsselwort des Codeschnippels „function“ ist. Und hier kommen wir schon zum Knackpunkt der Objektorientierung in Javascript: Es wird nicht zwischen Objekten und Funktionen unterschieden.

Der mit Abstand größte Vorteil der objektorientierten Javascript-Programmierung ist die bessere Speicherkontrolle. Gerade bei modularen Websites kann es aufgrund von Caches notwendig sein, dass alle Skriptdateien im Vorfeld geladen werden. Muss der Browser nun alle Funktionen im globalen Sichtbarkeitsbereich erstellen, braucht das neben Speicher auch CPU-Zeit. Erstellt man jedoch Objekte, z.B. auch einfach nur „Controller“-Objekte, werden die Methoden erst bei der Instanziierung des Objekts „angelegt“. Um das allgemeiner zu formulieren: Der Code innerhalb des äußeren „function“-Schlüsselworts wird erst beim Aufruf dieser Funktion ausgeführt.

Um den Begriff „Controller“ in diesem Zusammenhang etwas genauer zu erklären, möchte ich euch einfach ein kleines Skript vorstellen, welches z.B. dazu dienen könnte, einen „Artikel weiterempfehlen“-Layer einzublenden:

function articleAdviseController(divId)
{
	var divElement = null;

	this.show = function()
		{
			divElement.style.display = 'block';
		}

	this.hide = function()
		{
			divElement.style.display = 'none';
		}

	divElement = document.getElementById(divId);
}

Um das obige Beispiel zu vervollständigen hier noch der Beispielaufruf (vielen Dank für den Kommentar von Bastian):

// Instanzierung, z.B. im HEAD-Bereich der Seite
var myArticleController = new articleAdviseController('my_div_id');
// Spätere Nutzung, z.B. im ONCLICK-Attribut eines Elements
<a onclick="myArticleController.show()">Kommentare zeigen</a>
<a onclick="myArticleController.hide()">Kommentare verstecken</a>

Zu guter Letzt noch ein kleiner Ausblick auf den nächsten Artikel, in dem ich speziell auf das Thema „Sichtbarkeit“ von Eigenschaften und Methoden eingehen möchte.

Über den Autor

Stephan Schulze

Kommentare

22 Comments

  1. Danke für den Artikel. Hat mich schon lange gewundert, dass das Thema Javascript hier noch nicht aufgegriffen wurde, obwohls so wichtig ist.

    Ich beschäftige mich auch seit einigen Wochen intensiver mit Javascript und auf meinem Blog werden voraussichtlich einige Artikel über dieses Thema erscheinen.

    Folgender Artikel ist bei mir gerade heute erschienen :-)
    http://daraff.ch/2010/08/javascript-lernen-javascript-java/

    Ausserdem gibt es folgende übers testen und mocken mit javascript:
    http://daraff.ch/2010/07/javascript-mocking-mit-jsmockito-teil-i/
    http://daraff.ch/2010/07/javascript-unit-testing-mit-jstestdriver/

    Dann noch eine Frage an die Community, bei welcher ich mich in Javascript noch schwer tue.
    1. Wo gibt es gute Beispiele für TDD Entwicklung mit Javascript?
    2. Da javascript in einer Anwendung teilweise sehr mit HTML verknüpft ist: Welche Teile einer Javascript Applikation/Webseite soll ich mit unit tests abdecken und wie? Beispiele? Kann man GUI’s sinnvoll mit unit tests testen oder sollte man eher sowas wie Selenium verwenden? Wo ist die Grenze?

    Würde mich sehr über eine Antwort und über gute Quellen freuen.

    Reply
  2. Interessanter Artikel. Ein paar Verbesserungsvorschläge: Beim letzten Script fehlt ein Beispielaufruf und dein „Ausblick“ auch den nächsten Artikel ist etwas merkwürdig :-) Sonst ist der Artikel gut.

    Reply
  3. Hallo Bastian,

    vielen Dank für deine konstruktive Kritik. Ein Beispielaufruf hätte an dieser Stelle wirklich nicht geschadet. Da will ich mal eben sehen, was da zu machen ist 😉

    Edit: Entsprechende Code-Beispiele wurden hinzufügt.

    Viele Grüße,
    Stephan

    Reply
  4. Mir fehlt im Artikel der Hinweis das es es nicht nur diese eine Art gibt in JavaScript objektorientiert zu programmieren(Stichwort prototyping). Weiterhin erwähnst du das es zwar keine Keywords für public oder private gibt, es aber doch möglich ist Member-Variablen als public oder private zu deklarieren. Das JavaScript keine Konstruktor kennt stimmt auch nicht. In deinem Beispiel ist der Konstruktor halt gleichzusetzen mit der Klassendefinition. Noch eine andere Frage. Wieso weist du einer Variable nicht gleich bei der Deklaration den Wert zu? Ich weiß das ist Geschmackssache, finde aber es erhöht die Lesbarkeit um ein vielfaches wenn man alles in eine Zeile schreibt.

    Reply
  5. Hallo Christian,

    ja, ich kenne die Methode des „prototypings“ auch. Jedoch ist dies mMn für ein „Einsteiger“-Thema ein Stück zu weit gegriffen, da es sich doch teilweise recht deutlich von PHP-Entwicklung abhebt.

    „private“ und „public“-Schlüsselwörter gibt es nicht, dass es dennoch geht, sollte an den Code-Beispielen deutlich werden. Auf das Thema „Sichtbarkeit“ soll es im nächsten Artikel gehen.

    Die Variablen-Zuweisung bei Initialisierung nutze ich in der Entwicklung meistens, da es die Lesbarkeit erhöht. In dem Beispiel zielte ich auf Parallelen zwischen der PHP-Funktion „__construct()“ und dem Javascript-Code, um, wie oben bereits beschrieben, den Einstieg etwas leichter zu gestalten.

    Viele Grüße,
    Stephan

    Reply
  6. Ist das nicht ein ziemlicher Overhead bei jedem new die Methoden neu zu deklarieren? Oder findet das der Interpreter heraus und optimiert es?

    Wolfgang

    Reply
  7. Hallo Wolfgang, hallo Markus,

    vielen Dank für eure Kommentare:

    @Wolfgang:
    Der Interpreter baut, so sieht es zumindest in Performance Messungen aus, das „Gerüst“ genau einmal beim „new“ Aufruf und hält es dann im Speicher, so dass ein zweiter „new“ Aufruf deutlich schneller ist.

    @Markus:
    Schon in Arbeit 😉

    Viele Grüße,
    Stephan

    Reply
  8. Sehr schoener Artikel fuer Einsteiger, aber er vermittelt mir zu sehr den Eindruck, dass Javascript nichts weiter ist als eine weitere prozedurale Programmiersprache, was schlichtweg nicht der Fall ist.

    Fuer alle, die nicht lange genug auf die naechsten Artikel warten koennen sind durchaus die zwar mittlerweile leicht angestaubten, aber dadurch nicht schlechteren Artikel von Douglas Crockford zu empfehlen http://www.crockford.com/

    Reply
  9. Hallo,

    zum einen erst mal ein Lob ans gewählte Thema, genau das was ich brauche, ich bin genau die Zielgruppe 😉

    Freue mich schon auf die nächsten Artikel.

    Was das Thema Konstruktor angeht, ich glaube Stephan ging es eher darum zu sagen, dass es hier eben nicht einen Konstruktor in Form einer Methode wie __construct() in PHP oder __init__(self) in Python (oder … in …) gibt.

    Gruß Sebastian

    Reply
  10. @Sebastian

    Das kann man so nicht sagen da es eine Konstruktor-Methode in JavaScript gibt.

    /**
    * Constructor
    */
    function Car(maxSpeed) {

    this.speed = 0;
    this.maxSpeed = maxSpeed;
    }

    Car.prototype.accelerate() {

    while (this.speed <= this.maxSpeed) {
    this.speed++;
    }
    }

    var car = new Car(100);
    car.accelerate();

    Reply
  11. Hallo Christian,

    gerne wollte ich in dem ersten Artikel auf das Thema „prototyping“ verzichten, um die Übersichtlichkeit gerade für Einsteiger zu wahren.

    Für alle Interessierten weise ich mal an dieser Stelle darauf hin, dass sich ein eigener Artikel mit dem Thema „prototyping“ beschäftigen wird.

    Viele Grüße,
    Stephan

    Reply
  12. Hallo Stephan,

    ich habe das Beispiel auch nur ausgepackt weil man mit prototyping besser sieht das der Konstruktor eine eigene Methode/Funktion ist.

    Sorry wenn ich deine Planung jetzt durcheinander gebracht habe. (o;

    Reply
  13. Hallo Christian,

    man sieht schon, dass das hier wohl eine ganze Diskussion wird – aber so soll es ja auch sein und ich bin für Anregungen jederzeit sehr dankbar.

    Und kein Grund für eine Entschuldigung 😉 Ich denke, für die Leser ist es ohne Zweifel auch interessant, wo es hingeht.

    Viele Grüße und danke für die sachliche Diskussion zu diesem Thema,
    Stephan

    Reply
  14. (Anscheinend ist mein letzter Kommentar nicht durchgekommen?)

    Wer etwas tiefer in JavaScript-OOP einsteigen will, dem sei meine Textreihe Organisation von JavaScripten empfohlen:
    http://molily.de/weblog/javascript-organisation

    Dort speziell der Artikel über Konstruktoren, Prototypen und Instanzen:
    http://molily.de/js/organisation-instanzen.html

    Die Einleitung erklärt, was JavaScript-OOP von z.B. PHP unterscheidet und welche Konzepte fortgeschrittenes JavaScript prägen:
    http://molily.de/js/organisation-ueberblick.html

    Reply
  15. Wenn ich mir die Funktion articleAdviseController so anschaue… was ist denn aus „Tell, don’t ask!“ geworden? Die ID wird doch nur übergeben, um dann von einem Objekt document (wo kommt das her*?) etwas zu holen. Wäre ein Beispiel, welches stattdessen direkt das Element bekommt, nicht besser gewesen? Oder noch besser: Direkt das style-Objekt, der Rest wird gar nicht benutzt.

    Immerhin sollen diese Funktionen ja beispielhaft sein und sollten daher möglichst sauber sein.

    * Rhetorische Frage, ich weiß, was das ist. 😉

    Reply
  16. Mini-Kritik an einem Detail:

    Ich lese
    „// Instanzierung, z.B. im HEAD-Bereich der Seite“

    Javascript sollte, wenn möglich, nie im Headbereich einer Seite stehen.

    Reply

Leave a Comment.

Link erfolgreich vorgeschlagen.

Vielen Dank, dass du einen Link vorgeschlagen hast. Wir werden ihn sobald wie möglich prüfen. Schließen