Tommy G.: Objektorientierung und Methoden

Hallo zusammen,

ich habe hier gerade ein Problem und wollte einfach mal nachfragen, ob mir hier jemand weiterhelfen kann.

Ich habe mir in JS ein kleines Objekt geschrieben mit dem Namen Controller.

"function Controller(){}"

Soviel zur Deklaration. Nun füge ich über das Schlagwort "prototype" einige Methoden und Attribute hinzu.

  
    Controller.prototype.setConfig = function () {  
        this.sendRequest();  
        this.setStandartFunctions();  
    }  

Innerhalb einer dieser Methoden möchte ich nun eine andere Methode des Objekts aufrufen.

  
    Controller.prototype.setStandartFunctions = function () {  
        $('.buttonNewData').bind('click',function() {  
            Controller.prototype.startLayerControl('create');  
        });  
        $('.editDataSet').bind('click',function() {  
            Controller.prototype.startLayerControl('edit',$(this));  
        });  
        $('.deleteDataSet').bind('click', function() {  
        var selectedRow =            $(this).parent().children();				  
        var deleteBox = Controller.prototype.setDeleteDataDialogTemplate();  
  
        $(this).append(deleteBox);  
        $('#deleteBox').dialog({  
            height: 110,  
            width:	200,  
        });  
  
        Controller.prototype.setDeleteTemplateConfig();  
    });  
}  

An dieser Methode kann man nun schon mein "Problem" erkennen. Ich rufe andere Methoden desselben Objekts immer mit "Controller.prototype.[Methode]" auf. In den meisten Fällen funktioniert das, allerdings nicht bei allen.

this.[Methode] kann ich nicht verwenden, da sich das this auf das HTML Element, wo das event ausgelöst wurde, bezieht. Controller.prototype.[Methode] setzt die Funktionalität der Methode allerdings immer wieder neu auf das Element, da ich hier mit anonymen Funktionen arbeite. Ich schätze einfach mal, dass hier das problem liegt.

Lange Rede kurzer Sinn, wie kann ich eine Methode einer Klasse innerhalb einer anderen Methode aufrufen.

Ich hoffe ich konnte die Problemmatik verständlich erklären.

Ich hoffe auf schnelle Antworten.

Viele Grüße,

Tommy

  1. Hi,

    mit closures.

    ~dave

    1. Hi Dave,

      jepp danke! Der Artikel hat mir den nötigen Anstoß gegeben. Ich setze beim Anlegen eines Objekts nun eine Referenz auf die Klasse fest und gebe die einfach mit beim Aufruf der Methoden.

      Das war schon alles! :-)

      Viele Grüße

      Tommy

  2. Lieber Tommy,

    1.)

    this.setStandartFunctions();

    Du meinst sicherlich nicht die Standarte.

    2.)

    $('.buttonNewData').bind('click',function() {
                Controller.prototype.startLayerControl('create');
            });

    Du verwendest ein Framework wie jQuery oder sowas. Das musst Du bei Fragen dieser Art unbedingt angeben!

    3.)
    Dich interessiert der Artikel Organisation von JavaScripten, insbesondere das Kapitel Object-Methoden in anderen Kontexten ausführen.

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:| n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hallo Felix,

      zunächst danke für die schnelle Antwort.

      Sorry, dass ich jQuery verwende, scheint irgendwie "rausgerutscht" zu sein. Ich verwende hier sowohl jQuery, als auch jQuery UI.

      Also wenn ich das nun richtig verstanden habe, darf hier (wie ich es bereits auch mache) auf das Schlüsselwort "this" nicht verwendet werden. Stattdessen müsste ich hier Controller.setDeleteTemplateConfig(). Oder bzw Instanzname.setDeleteTemplateConfig().

      Habe ich das hier nun richtig verstanden. Denn damit komme ich leider nicht weiter. Das habe ich alles schon versucht und hat mich dazu bewogen diese Frage hier zu stellen.

      Könnte das "prototype" hier vielleicht Probleme machen ?

      Ich schaue mir den Artikel nochmal etwas genauer an.

      Vielen Dank soweit.

      Tommy

  3. Hallo,

    irgendwie hast du da etwas grundsätzlich missverstanden über Konstruktorfunktionen, Prototypen und Instanzen.

    Was du machst (zumindest der Code, den du gezeigt hast), hat nichts mit »Klassen«, aber auch nichts mit prototypischer Vererbung bzw. Konstruktoren/Instanzen zu tun. Du definierst ein einzelnes Objekt und rufst dann dessen Methoden auf. Dazu brauchst du kein Prototyp, das geht auch mit einem stinknormalen Objekt-Literal. Am besten liest du dir mal diese Artikel durch, um die Unterschiede und die Terminologie zu verstehen:

    Organisation von JavaScripten: Voraussetzungen und Überblick
    Module und Kapselung, darunter Objekt-Literale
    Konstruktoren, Prototypen und Instanzen
    Objektverfügbarkeit und this-Kontext

    So richtig verstehe ich nun nicht dein Problem und auch nicht, wie Closures es lösen sollen. Du kannst von jeder Stelle problemlos auf das globale Objekt Controller.prototype und dessen Eigenschaften zugreifen. Das ist völlig üblich, wenn man einen Objekt-Literal als Namensraum bzw. »Singleton« verwendet. Das zeigt beispielhaft Felix Riesterers Artikel, dort wird FaderFramework als Objekt-Literal notiert (darin übrigens ein Konstruktor). Eine Funktion und dessen prototype-Eigenschaft ist dazu wie gesagt unnötig, ein einfaches Objekt reicht.

    Erst wenn du mit Instanzen arbeitest -- die mit Konstruktoren mittels »new« erzeugt werden und von Prototypen erben bzw. an diese delegieren --, dann ergibt sich das Problem, wie man in Event-Handlern auf die Instanz zugreift. Da gibt es verschiedene Ansätze, die im letztgenannten Text geschildert sin. Und jQuery bringt zudem noch eigene mit: jQuerys bind() sowie deren abgekürzte Varianten wie click() kennen beispielsweise einen Kontext-Parameter (eventData), mit dem man einfach Objekte, in diesem Fall z.B. das Instanzobjekt, ohne Closures in den Event-Handler hineingeben kann. Innerhalb des Handlers kommt man über event.data an das übergebene Objekt.

    Grüße,
    Mathias

    1. Hallo,

      ich hatte übersehen, dass du anscheinend durchaus Konstruktoren/Instanzen und Prototypen verwendest. Sorry für das Missverständnis. Tipps für den Fall hatte ich trotzdem gegeben, der Artikel http://molily.de/js/organisation-verfuegbarkeit.html beschäftigt sich damit, alternativ kannst du eben den eventData-Parameter von jQuery verwenden.

      Grüße, Mathias

  4. Ich habe mir in JS ein kleines Objekt geschrieben mit dem Namen Controller.

    "function Controller(){}"

    Das ist noch kein Objekt, sondern eine Konstruktorfunktion.

    Soviel zur Deklaration. Nun füge ich über das Schlagwort "prototype" einige Methoden und Attribute hinzu.

    Controller.prototype.setConfig = function () {
            this.sendRequest();
            this.setStandartFunctions();

    sorry für den Hinweis, aber das tut weh [link:http://www.k-faktor.com/standart/]

    Aber das Javascript ist bisher i.O.

    Innerhalb einer dieser Methoden möchte ich nun eine andere Methode des Objekts aufrufen.

    Nicht ganz, du willst innerhalb von Eventfunktionen auf das Objekt zugreifen.

    [code lang=javascript]
        Controller.prototype.setStandartFunctions = function () {
            $('.buttonNewData').bind('click',function() {
                Controller.prototype.startLayerControl('create');
            });

    [...]

    An dieser Methode kann man nun schon mein "Problem" erkennen. Ich rufe andere Methoden desselben Objekts immer mit "Controller.prototype.[Methode]" auf. In den meisten Fällen funktioniert das, allerdings nicht bei allen.

    Das ist auch falsch, du willst hier vermutlich auf die Instanz deines Objektes zugreifen, damit diese in der Eventfunktion zu verfügung steht, musst du diese lokal kopieren.

    Grob sieht das so aus:
    [code lang=javascript]Controller.prototype.setStandartFunctions = function () {
    var _this = this; // Kopie
     $('.buttonNewData').bind('click',function() {
                 _this.startLayerControl('create');
             });
    [...]

    Bei den anderen Aufrufen, kannst du das \_this ebenfalls verwenden.  
      
    Struppi.