Faber: Merkwürdiges Problem mit Sichtbarkeit

Hi zusammen,

ich bin auf ein Problem gestoßen, welches ich nicht verstehe, aber ihr mir sicher schnell erklären könnt. Folgende Situation:

function Klasse1(){  
	klasse2_instanz1	=	new Klasse2("rot");  
	klasse2_instanz2	=	new Klasse2("blau");  
  
	klasse2_instanz1.farbe();  
}  
  
function Klasse2(farbe){  
	zeigeFarbe	=	function(){  
		alert(farbe);  
	}  
	this.farbe	=	function(){  
		zeigeFarbe();  
	}  
}  
  
new Klasse1()

Anstatt 'rot' zu melden, gibt der Code für klasse2_instanz1 'blau' aus. Prinzipiell ist es so, dass immer der Parameter des zuletzt instanzierten Objektes ausgegeben wird.

Wenn das alert(farbe) allerdings in die öffentliche Funktion this.farbe() gepackt wird (ohne umweg über die private zeigeFarbe()), wird die richtige Farbe ausgegeben.

Wieso verdammt ist das so? ;-)

Ich hoffe ihr könnt mir behilflich sein.

Viele Grüße

Faber

  1. Wahrscheinlich liegts daran dass du die Funktion zeigeFarbe() neu definierst und sie dann als Parameter fest "blau" enthält.

    Das sind übrigens ziemlich schräge Konstrukte die du da machst, ich hab erst eine ganze Zeit lang überlegt was du da machst. Hat das eine praktische Bedeutung oder ist das nur zum experimentieren? Falls a) dann würd ich das an deiner Stelle entschärfen, denn das kapierst du nämlich eine Woche später selber nicht mehr.

    1. Wahrscheinlich liegts daran dass du die Funktion zeigeFarbe() neu definierst und sie dann als Parameter fest "blau" enthält.

      Genau!

      Gültigkeitsbereich:

      zeigeFarbe -> GLOBAL
      var zeigeFarbe -> LOKAL

      Ein "var" sollte das Problem lösen.

      Gruß
      peter

      1. Wahrscheinlich liegts daran dass du die Funktion zeigeFarbe() neu definierst und sie dann als Parameter fest "blau" enthält.
        Genau!

        Gültigkeitsbereich:

        zeigeFarbe -> GLOBAL
        var zeigeFarbe -> LOKAL

        Ein "var" sollte das Problem lösen.

        Gruß
        peter

        Ja das ganze hat auch einen praktischen Sinn. Ich habe meinen Code nur bis auf das Problem reduziert. Eigentlich hab ich eine Klasse Analogmeter, die mir ein entsprechendes Analogmeter mit Raphael zeichnet. Da das ganze aber ziemlich unübersichtlich geworden ist in einer Klasse hab ich das mal refaktorisiert. Heraus kam dann eine solche Struktur:

        function Analogmeter(){  
        	skala1	=	new Skala("Ampere");  
        	skala2	=	new Skala("Volt");  
          
        	skala1.zeichneSkala();  
        }  
          
        function Skala(name){  
        	zeichneName	=	function(){  
        		alert(name);  
        	}  
        	this.zeichneSkala	=	function(){  
        		zeichneSkalenstriche();  
        		zeichneName();  
        		zeichneKreisbogen();  
        	}  
        }
        

        Ich denke das macht schon Sinn so. Für Vorschläge bin ich aber immer offen ;-)

        Und was die Lösung angeht: mit var vor jeder privaten Funktion klappt es tatsächlich, vielen Dank!

        Aber ich verstehe nicht so recht wie eine private Funktion global definiert sein kann?! Und ist dann this.zeichneSkala() bzw. this.farbe() auch global definiert?

        1. Funktionen sind global. Ich weiß nicht ob man in Javascript für jedes Objekt eine eigene private Funktion zusammendefinieren kann. Würd ich aber auch nicht tun, denn da blickt dann keiner mehr wirklich durch.
          Ich würd die Funktionen so definieren
          function zeichneSkala()
          {
           zeichneSkalenstriche();
           zeichneName();
           zeichneKreisbogen();
          }
          Nicht im Konstruktor, sondern einfach im Code. Alles nötige übergibst du dann beim Aufruf, oder hältst es als Feld innerhalb einer Klasse.

          1. Funktionen sind global. Ich weiß nicht ob man in Javascript für jedes Objekt eine eigene private Funktion zusammendefinieren kann. Würd ich aber auch nicht tun, denn da blickt dann keiner mehr wirklich durch.
            Ich würd die Funktionen so definieren
            function zeichneSkala()
            {
            zeichneSkalenstriche();
            zeichneName();
            zeichneKreisbogen();
            }
            Nicht im Konstruktor, sondern einfach im Code. Alles nötige übergibst du dann beim Aufruf, oder hältst es als Feld innerhalb einer Klasse.

            Hm, aber die this.zeichneSkala() scheint ja lokal zu sein, denn daraus kann ich auch den richtigen Skalennamen abrufen. Wird dann zeichneSkala() durch "this." quasi direkt dem Objekt zugeordnet und ist lokal?

            Wenn ich deinen Vorschlag richtig verstanden haben wäre damit die Klasse Skala überflüssig, denn mehr als eine Skala zeichnen macht sie letztendlich nicht.
            Damit wäre wiederum die Objektorientiertung hin, die ich eigentlich für bessere Übersichtlichkeit angestrebt hatte. Aber ich Implementierung von OOP ist eh sehr merkwürdig geraten, wie ich an meinem Problem merke.

            1. Vielleicht kannst du in JS tatsächlich jedem Objekt eine "personalisierte" Funktion anhängen. Aber das würd ich nicht tun. Da hättest du eine wahnsinns Arbeit.

              Aber ich Implementierung von OOP ist eh sehr merkwürdig geraten, wie ich an meinem Problem merke.

              Deine ja ;-)
              Was du anstrebst ist nicht "eine Funktion für alle", sondern "jedem seine eigene Funktion".

              Objektorientierung ist nicht wenn man jedem Objekt eigene Funktionen gibt, sondern wenn eine Klasse (und somit jedes Objekt von diesem Typ) Funktionen hat, die für alle Objekte dieser Klasse gelten. Diese Funktionen nutzen dann die Variablen des jeweiligen Objekts.

              Also es gibt eine Funktion die einen Namen ausgibt, z.B. this.Name. Das holt sich den Wert, der im aktuellen Objekt. Aber dafür braucht nicht jedes Objekt eine eigene Funktion definiert haben.

              1. Objektorientierung ist nicht wenn man jedem Objekt eigene Funktionen gibt, sondern wenn eine Klasse (und somit jedes Objekt von diesem Typ) Funktionen hat, die für alle Objekte dieser Klasse gelten. Diese Funktionen nutzen dann die Variablen des jeweiligen Objekts.

                Eigentlich strebe ich genau das an ;-)

                Vielleicht orientiere ich mich da zu sehr an dem, was ich von Java kenne. Dort hätte ich ja sowas ungefähr:

                public class Analogmeter{

                public Analogmeter(){
                        private Skala skala1        =        new Skala("Ampere");
                        private Skala skala2        =        new Skala("Volt");

                skala1.zeichneSkala();
                   }
                }

                public class Skala{
                    private String name;

                public Skala(String neuerName ){
                        name = neuerName;
                    }
                        private void zeichneName(){
                                alert(name);
                        }
                        public void zeichneSkala(){
                                zeichneSkalenstriche();
                                zeichneName();
                                zeichneKreisbogen();
                        }
                }

                Aber wenn ich dich jetzt richtig verstanden habe, kann ich nicht wie in Java in der Klasse Skala eine private Funktion definieren, die mit den Variablen der Instanz arbeitet, sondern müsste außerhalb der Klasse eine Funktion zeichneSkala() definieren und der die Variablen mitgeben. Denn mit this.irgendeineFunktion() und var irgendeineFunktion() werden die Funktionen immer direkt für die Instanz und nicht die Klasse definiert?!

            2. Hi,

              Hm, aber die this.zeichneSkala() scheint ja lokal zu sein, denn daraus kann ich auch den richtigen Skalennamen abrufen. Wird dann zeichneSkala() durch "this." quasi direkt dem Objekt zugeordnet und ist lokal?

              http://phrogz.net/JS/Classes/OOPinJS.html

              MfG ChrisB

              --
              “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
        2. Hi,

          Aber ich verstehe nicht so recht wie eine private Funktion global definiert sein kann?! Und ist dann this.zeichneSkala() bzw. this.farbe() auch global definiert?

          http://de.selfhtml.org/javascript/sprache/index.htm

          Die Artikel über Variablen, Objekte und Funktionen sollten erstmal weiterhelfen.

          Gruß
          peter