Orlok: Schnittstellen

Beitrag lesen

Hallo

Wie einige von euch sicherlich festgestellt haben, liegt in Bezug auf die Struktur der JavaScript-Sektion im Wiki immernoch vieles im Argen, sprich, die Trennung des Sprachkerns ECMAScript von den verschiedenen Schnittstellen einerseits, so wie andererseits auch die Abstraktion zwischen den diversen APIs selbst ist nach wie vor unzureichend, auch wenn es hier, dank des Engagements von Matthias Scharwies, gegenüber dem früheren Zustand bereits Fortschritte zu verzeichnen gibt.

Tatsächlich ist die korrekte Abbildung der diversen Schnittstellen, der built-in objects und ihrer Eigenschaften und Methoden keine ganz triviale Aufgabe, wobei die Arbeit hier unter anderem dadurch erschwert wird, dass im Wiki ja nicht bei null angefangen wird, sondern eine bereits bestehende Struktur transformiert werden muss.


Zur Veranschaulichung des Themas sei vielleicht zunächst ein kleines Beispiel angeführt:

(function (param) {
  var get = Object.getPrototypeOf;
  var proto = get(param), con;
  while (proto !== null) {
    con = proto.constructor;
    console.log(con.name || con);
    proto = get(con.prototype);
  }
}(document.body));

Hier haben wir zunächst einen anonymen IIFE (Immediately-Invoked Function Expression), welchem das Element Body als Argument übergeben wird, wobei dieses über die Eigenschaft gleichen Namens des Objektes document referenziert wird. Diese Eigenschaft stellt eine HTML-spezifische Erweiterung der Schnittstelle Document des DOM dar. In der Praxis bedeutet dies, dass die Eigenschaft mit dem Bezeichner body je nach Implementierung entweder eine eigene Eigenschaft des Objektes ist, welches in der prototype-Eigenschaft des Konstruktors HTMLDocument hinterlegt ist, oder aber sie wird direkt von Document.prototype an die Instanz document vererbt, wobei ich Letzteres für keine gute Entscheidung der einschlägigen Browserhersteller halte, da hierbei eigentlich separate Schnittstellen vermischt werden.

Innerhalb der Funktion wird nun zunächst die Methode getPrototypeOf des Konstruktors Object der lokalen Variable mit dem Bezeichner get als Wert zugewiesen. Wird dieser Methode bei ihrem Aufruf ein Objekt übergeben, dann gibt sie den Wert der internen Eigenschaft [[Prototype]] dieses Objektes zurück, also gewissermaßen den nächsten Vorfahren innerhalb der jeweiligen Prototypenkette.

Diese Methode wird nun in einem nächsten Schritt für den mit Body initialisierten Parameter der Funktion aufgerufen und der Rückgabewert in der Variable mit dem Bezeichner proto hinterlegt. Die folgende Schleife sorgt nun dafür, dass solange der Wert von proto nicht null ist, der Wert der prototype-Eigenschaft constructor in der Variable con gespeichert wird. Der Wert dieser Eigenschaft ist wie der Name schon vermuten lässt immer eine Referenz auf den jeweiligen Konstruktor, dessen Name in einem nächsten Schritt in die Konsole geschrieben wird, sofern die Eigenschaft name unterstützt wird. Dies geschieht freilich unter Verwendung des nicht standardisierten Console-API, dessen Instanzobjekt im globalen Namensraum Eigenschaft des von Browser bereitgestellten window-Objektes ist. Schließlich wird proto für den nächsten Schleifendurchlauf mit dem Prototypen des Vorfahren initialisiert. Die Prüfung gegen null erflogt hier, da dies der Wert der internen Eigenschaft [[Prototype]] von Object.prototype ist, welche das letzte Glied in der prototype chain darstellt. Im Ergebnis werden dann dem zur Folge durch die Funktion alle Namen der Konstrukoren eines Objektes in die Konsole geschrieben, was für Body im Firefox so aussehen würde:

HTMLBodyElement
HTMLElement
Element
Node
EventTarget
Object

Diese built-in objects repräsentieren hier also die verschiedenen Schnittstellen, die Eigenschaften und Methoden an das Objekt vererben, welches das Element Body repräsentiert, wobei sich die jeweiligen Implementierungen allerdings wie bereits gesehen in Details unterscheiden können.

Jedenfalls beginnt die Kette hier erwartungsgemäß mit Object, welches bekanntermaßen Teil des Sprachkerns ECMAScript ist. Dann haben wir hier die Schnittstelle EventTarget des DOM, welche unter anderem die Methode addEventListener an unser Element vererbt. Weiterhin werden Eigenschaften und Methoden der Schnittstellen Node und Element des Document Object Models vererbt, wie etwa die Eigenschaft textContent durch Node.prototype oder die Eigenschaft tagName durch Element.prototype. Schließlich vererben die HTML-spezifischen Schnittstellen HTMLElement und HTMLBodyElement eigene Eigenschaften wie beispielsweise offsetTop oder onhashchange.

Es wird also deutlich, dass wenn es das Ziel des Wikis sein soll, eine halbwegs präzise Vorstellung vom Zusammenwirken der verschiedenen Schnittstellen zu vermitteln, der Aufbau der Sektion auch die tatsächlichen Strukturen entsprechend soweit wie möglich widerspiegeln sollte, womit wir dann beim derzeitigen Stand der Dinge angelangt wären.


Dem aufmerksamen Beobachter wird wie eingangs bereits erwähnt aufgefallen sein, dass sich in der letzten Zeit hier durchaus einiges getan hat. So wurde beispielsweise die Rubrik DOM aus der Rubrik Objekte herausgelöst und bestehende Artikel wurden neu gegliedert.

Nichtsdestotrotz ist die Aufteilung meiner Ansicht nach jedoch noch nicht ideal. Zwar sind nun innerhalb der Rubrik Objekte die built-in objects von ECMAScript, also etwa Object, Function oder Math, von nicht zugehörigen Objekten optisch abgesetzt aufgelistet, jedoch sollten diese nicht zum Sprachkern gehörigen Objekte im Sinne einer strikten Trennung von Sprache und Schnittstellen dort eigentlich gar nicht stehen, sondern statt dessen unter APIs aufgeführt sein. – Also, nochmal zur Verdeutlichung, im Moment sieht es so aus:

Objekte

  • navigator
  • screen
  • window
    • document
      • forms
        • elements
    • history
    • location

|und davon leicht abgesetzt|

  • Object
  • Array
  • Boolean
  • Date
  • Function (usw.)

Hier fällt zunächst einmal auf, dass mindestens einmal der Artikel zu document deplaziert ist. Das Instanzobjekt document ist zwar wie alle eingebauten Objekte als Bestandteil des globalen Namensraums Eigenschaft des Objektes window, aber im Sinne der inhaltlichen Zugehörigkeit sollte dieser Artikel neben node unter der Rubrik DOM aufgeführt sein, dessen Schnittstelle Document es repräsentiert, und bei den Eigenschaften von window lediglich verlinkt werden. Was die forms-Schnittstelle angeht, so handelt es sich hier ebenso wie bei der Dokumenteigenschaft body aus dem Eingangsbeispiel um eine HTML-spezifische Erweiterung der Schnittstelle Document des DOM. Dazu aber später noch etwas mehr.

Jedenfalls denke ich, dass die Punkte Window, Screen, Location, Navigator und History am besten unter einer gemeinsamen Rubrik Browser zusammengefasst werden sollten, wobei die Objekte zwar auch als Eigenschaften von window aufgeführt und entsprechend verlinkt sein sollten, sie jedoch wie ich meine davon abgesehen als separate Punkte aufgelistet gehören.

Browser

  • Window
    • document (link)
    • innerHeight
    • innerWidth
    • navigator (link)
  • Navigator
  • History
  • Location
  • Screen

Die Auswahl an Unterpunkten zu Window ist jetzt hier nur zu Demonstrationszwecken aufgelistet. Auf der Startseite der JavaScript-Sektion würde es wohl genügen wenn die entsprechenden Listenpunkte erst beim Klick auf die Überschrift Browser beziehungsweise auf Window sichtbar werden. Darüber hinaus denke ich, dass diese gemeinsame Rubrik Browser ebenso wie zuvor schon die Rubrik DOM aus Objekte herausgelöst und auf die rechte Seite des Zwei-Spalten-Layouts verfrachtet werden sollte.

Es bietet sich in dieser Hinsicht wie ich meine gerade zu an, die beiden Spalten zur Trennung von Sprachkern und Schnittstellen zu verwenden und entsprechende Überschriften einzufügen. Denn momentan ist es ja noch so, dass von der Vermischung innerhalb von Objekte einmal abgesehen, auch die Überschriften auf der rechten Seite des Layouts etwas missverständlich sind:

  • DOM
  • Event
  • APIs

Denn einerseits sind Event und EventTarget Schnittstellen des DOM, und andererseits ist das Document Object Model selbst natürlich auch eine Ansammlung von Schnittstellen, weshalb hier beim dritten Punkt wenn überhaupt die Überschrift andere APIs sinnvoll erschiene.

Jedenfalls habe ich mir über diesen Aspekt meine Gedanken gemacht und bin zu dem Ergebnis gekommen, dass es erstens, im Gegensatz etwa zur Handhabung im MDN, nicht sinnvoll ist, die „Web-APIs“ aus der JavaScript-Sektion vollkommen auszugliedern, zumindest nicht, solange JavaScript als Sprache der Browser keine ernsthafte Konkurrenz erwächst, und dass es zweitens notwendig ist, wenn man sich schon entscheidet, die Schnittstellen grundsätzlich in dieser Sektion des Wikis zu belassen, sowohl durch Überschriften als auch hinsichtlich der optischen Gliederung die Trennung von Sprachkern und APIs klar zu kommunizieren. Ich würde also dazu tendieren, die Überschrift APIs als globale Überschrift für die rechte Spalte einzusetzen, so dass diese Seite hernach etwa so auschauen würde:

APIs

  • DOM

    • Document
    • Node
    • Event (usw.)
  • Browser

    • Window
    • History (usw.)
  • Console

  • Geolocation

  • File Upload

  • WebGL (usw.)

Dabei sollte man vielleicht auch darüber nachdenken, ob APIs als Überschrift allein aus Anfängersicht gesehen so aussagekräftig ist. Vielleicht wäre es doch besser hier von ‚Schnittstellen‘ zu sprechen!?

Um abschließend nocheinmal auf die Abgrenzung zwischen DOM und HTML zurückzukommen: Ich denke, hier muss nicht zwingend eine eigene Rubrik eingerichtet werden, schon allein weil die Implementierungen hier nicht immer einheitlich sind, aber es sollte sowohl bei der Beschreibung der DOM-Objekte als auch bei der Auflistung der Eigenschaften und Methoden so klar wie möglich abgegrenzt werden.


Soweit meine Ansicht zum Thema. Vielleicht hat ja noch jemand Ideen, wie die Sektion besser zu gliedern wäre? Das würde mich interessieren! Und ich möchte am Ende auch noch einmal darauf hinweisen, dass unabhängig von den geäußerten Erwägungen gerade in der DOM-Rubrik ein paar ausführlichere Beschreibungen von Nöten sind. – Es wäre toll, wenn sich da jemand einbringen würde! ;-)

Gruß,

Orlok

--
„Das Wesentliche einer Kerze ist nicht das Wachs, das seine Spuren hinterlässt, sondern das Licht.“ Antoine de Saint-Exupéry

akzeptierte Antworten