MartinK: Zugriff von Objektmethode auf Objekteigenschaft

Hallo,

ich möchte für eine GoogleMaps-Anwendung eine eigene JS-Klasse bauen, die innerhalb einer Objektmethode auf einen Objektparameter zugreifen oder eine andere Objektmethode aufrufen soll.  Eigentlich ganz einfach, aber anscheinend habe ich irgendwo einen Denkfehler... der Zugriff läuft ins Leere.
Kann mir jemand sagen, was ich falsch mache?

  
function MyObject (){  
  
	this.Parameter=5;  
	this.Marker = new GMarker(new GLatLng(0,0));  
		  
	GEvent.addListener(this.Marker, 'click', this.myFunction);  
	  
	Map.addOverlay(this.Marker);  
		  
}  
  
MyObject.prototype.myFunction = function (){  
		alert(this.Parameter);  
};  
  
  
Map = new GMap2(document.getElementById('map'));  
Map.setCenter(new GLatLng(0,0), 7);  
	  
  
a = new MyObject();  

Danke schon mal! :)
Martin

  1. Hallo,
    Ich vermute Dein Problem liegt hier:

    GEvent.addListener(this.Marker, 'click', this.myFunction);

    Dies übergibt zwar das Funktionsobjekt "this.myFunction" - aber eben nur das Funktionsobjekt. Wenn der Listener ausgeführt wird, kennt dieser die Referenz auf "this" nicht mehr:

    MyObject.prototype.myFunction = function (){
    alert(this.Parameter);
    };

    "this" bezieht sich hier nicht mehr auf die Instanz von MyObject (sondern vermutlich auf GEvent)!

    Eine Mögliche Lösung: Du übergibst die aktuelle Instanz als Variable, um den Scope so in den Listener "herrüber zu retten".

      
      
    function MyObject (){  
      
            this.Parameter=5;  
            this.Marker = new GMarker(new GLatLng(0,0));  
      
            GEvent.addListener(this.Marker, 'click',  
               this.myFunction(this));  
            Map.addOverlay(this.Marker);  
      
    }  
      
    MyObject.prototype.myFunction = function (instance){  
                    alert(instance.Parameter);  
    };  
      
    
    

    Eine andere Möglichkeit:

      
    function MyObject (){  
      
            this.Parameter=5;  
            this.Marker = new GMarker(new GLatLng(0,0));  
      
            var scope = this;  
            var listener = function () {scope.myFunction();};  
      
            GEvent.addListener(this.Marker, 'click', listener);  
            Map.addOverlay(this.Marker);  
      
    }  
      
      
    MyObject.prototype.myFunction = function (){  
                    alert(this.Parameter);  
    };  
      
    
    

    (ohne Gewähr ;) )

    Hope that helps.

    Viele Grüße,

    Jörg

    1. Hallo Jörg,

      vielen Dank für die ausführliche Hilfe. Mit der 2. Möglichkeit hauts hin. Bei der ersten wird beim Laden der Seite das Event einmalig ausgelöst, durch Klicken aber nicht. Aber egal. :)

      Gruß,
      Martin

    2. Hi,

      GEvent.addListener(this.Marker, 'click',
                 this.myFunction(this));

      Das führt die Funktion aus und übergibt den Rückgabewert an addListener. Der Rückgabewert ist aber keine Funktion, sondern in diesem Fall undefined.

      var listener = function () {scope.myFunction();};

      Eine Closure anzulegen ist letztlich der richtige Weg, am besten macht man das mit einer Binding-Helferfunktion, sodass man schreiben kann:

      GEvent.addListener(this.Marker, 'click', this.myFunction.bind(this));

      Das erzeugt genau wie oben eine Closure, die eine Referenz auf das Instanzobjekt einschließt und dann den tatsächlichen Handler im Kontext dessen aufruft (mit call() bzw. apply()).

      Übrigens ist Scope der falsche Begriff für das, worauf this zeigt. Der richtige Begriff ist Kontext (context). Der Scope spielt bei der Identifier Resolution eine Rolle. Das ist nochmal etwas anderes.

      Mathias

      1. Eine Closure anzulegen ist letztlich der richtige Weg, am besten macht man das mit einer Binding-Helferfunktion

        ... wie auch im verlinkten Artikel beschrieben:

        Alternativlösungen zur Kontext-Problematik: bind() und bindAsEventListener()

      2. Hallo,

        Das führt die Funktion aus und übergibt den Rückgabewert an addListener. Der Rückgabewert ist aber keine Funktion, sondern in diesem Fall undefined.

        Hups, ja Du hast recht. Mea culpa - war wohl zu spät gestern  :)