Rolf B: Manöverkritik: OOP in JS

Beitrag lesen

Hallo Felix,

Was meint ihr dazu?

(1) Sowohl Wiki als auch Du sind im Irrtum mit der Aussage, dass das this-Objekt in diesem Fall das Eventobjekt ist. Das Eventobjekt wird grundsätzlich als Parameter übergeben. Der Wert von this hängt von der Art der Registrierung ab.

Das ist in einer unheiligen Allianz von DOM und WebIDL Spec exakt festgelegt. Die WebIDL Spec hat einen Abschnitt "Call a user object's operation", die den Umgang mit einem Callback festlegt, und in der DOM Spec steht, dass beim Aufruf eines Eventlisteners für das registrierte Eventlistener-Objekt "call a user object's operation" mit der Operation "handleEvent", Argument "event-Objekt" und thisArg "currentTarget" auszuführen sei. Und in der WebIDL Spec steht dann, dass das Objekt entweder "Callable" sein kann oder ein Objekt mit einer Eigenschaft, die dem Operationsnamen entspricht. Im zweiten Fall wird thisArg durch das EventListener-Objekt ersetzt (WEBIDL 3.11, call a user object's operation, Step 10).

Demnach: Registriert man eine Funktion, enthält this den Wert von event.currentTarget (identisch mit dem Objekt, auf dem der Listener registriert wurde). Registriert man ein EventListener-Objekt, enthält this dieses Objekt.

Das ist auch sinnvoll, denn andernfalls käme man in der handleEvent-Methode nicht an die übrigen Eigenschaften des EventListener-Objekts heran.

Ich habe das vor ein paar Tagen auch hier notiert.

Was mich stört

Mich auch. Und dazu stört mich so einiges mehr.

(1) Anerkannte Application Patterns werden ignoriert

  • Person ist Model, nicht ViewModel, da gehören keine Handler für Klicks hin
  • Das click-Objekt der Person legt die Reaktion des Objekts auf einen Klick fest. Wie ein UI-Ereignis zu behandeln ist, entscheidet im MVVM Pattern der View und bei MVC der Controller. Nicht das ViewModel, nicht das Model.

(2) Verletzung von SRP (Single Responsibility Principle).

  • Die hit-Methode muss sich um zwei verschiedene Dinge kümmern: Ermitteln des richtigen this und Behandeln des Click-Events. Das ist falsch.

(3) Schlechte Namensgebung. Wieso heißt eine Methode, die das Alter anzeigt, "hit", und nicht "zeigeAlter"?

(4) Ich würde gerne eine Klarstellung haben - außerhalb des Wikis - ob ein EventListener Objekt noch Stand der Technik ist. Dieses Interface findet sich bereits im DOM Level 2 von 2003. Seitdem wurde die bind-Methode (ECMAScript 5.1, 2011) und Pfeilfunktionen (ECMAScript 2015) eingeführt, die das Problem ebenfalls lösen können und es - meine ich - eleganter tun.

MDN schreibt:

Note: Due to the need for compatibility with legacy content, EventListener accepts both a function and an object with a handleEvent() property function.

Angesichts der obigen Zeitleiste ist das Objekt mit handleEvent() Property die Legacy, nicht die Funktion. Wollen wir etwas promoten, das zwecks "compatibility with legacy content" existiert?

Die Pfeilfunktion wurde bereits von Felix gezeigt. Mit bind sähe es so aus:

object.addEventListener("click", p.zeigeAlter.bind(p));

und natürlich gibt's auch die gute alte function-Expression als Fallback.

Bind statt Pfeilfunktion hat eine Existenzberechtigung für Seiten, die Altbrowser unterstützen wollen/müssen. In Browsern, die bind nicht unterstützen, sollte man sich JavaScript besser nicht antun…

Aus meiner Sicht ist ein eventListener-Objekt dann und nur dann sinnvoll, wenn man ein bestimmtes Event unabhängig von einem Modellobjekt behandeln will, und eine Funktion dafür nicht ausreicht. Dafür kann es viele Anlässe geben. Aber zur reinen Delegation eines Events an eine Objektmethode ist es der falsche Ansatz, weil es dafür mittlerweile standardisierte Möglichkeiten gibt.

Rolf

--
sumpsi - posui - obstruxi