jobo: OO Backgroundcolorchanger - optimieren /Kontext von this

0 59

OO Backgroundcolorchanger - optimieren /Kontext von this

jobo
  • javascript
  1. 0
    unknown
    1. 0

      OO - optimieren /Kontext von this - was macht der Browser da?

      jobo
      1. 0
        unknown
        1. 0
          jobo
          1. 0
            unknown
            1. 0
              jobo
              1. 0
                unknown
                1. 0
                  jobo
                  1. 0
                    unknown
  2. 0
    ChrisB
    1. 0
      jobo
      1. 0
        ChrisB
        1. 0
          jobo
          1. 0
            molily
            1. 0
              jobo
      2. 0
        molily
        1. 0
          jobo
          1. 0
            molily
            1. 0

              OO bgColorChanger - next try: alles in einem Objekt

              jobo
              1. 0

                OO bgColorChanger - next try: alles in einem Objekt - kl. opt.

                jobo
                1. 0
                  unknown
                  1. 0
                    jobo
                    1. 0
                      jobo
                      1. 0

                        colorChanger - rein funktional - Feinschliff

                        jobo
                        1. 0
                          jobo
                          1. 0

                            colorChanger - Feinschliff en Detail, macht das Sinn?

                            jobo
                            1. 0
                              molily
                              1. 0
                                jobo
                                1. 0
                                  molily
                          2. 0
                            molily
                            1. 0
                              jobo
                              1. 0
                                unknown
                                1. 0
                                  jobo
                                  1. 0
                                    unknown
                                2. 0
                                  molily
                                  1. 0
                                    unknown
                  2. 2
                    molily
                    1. 0
                      unknown
                      1. 0
                        molily
                        1. 0
                          molily
                          1. 0
                            unknown
                            1. 0
                              jobo
                            2. 0
                              jobo
                            3. 0

                              OO bgColorChanger - mit Closure (verschachtelte Objekte)

                              jobo
                            4. 0
                              molily
                              1. 0

                                OO bgColorChanger - elegant oder zumindest vernünftig!

                                jobo
                    2. 0
                      jobo
                    3. 0

                      bgColorChanger - OO vs. funktional

                      jobo
                      1. 1
                        molily
                        1. 0
                          jobo
  3. 0

    OO - Zugriff auf Objektmethode mittels Namen als Stringparameter

    jobo
    1. 0
      unknown
      1. 0
        jobo
        1. 0
          ChrisB
          1. 0
            jobo
        2. 0
          unknown
    2. 0
      molily
      1. 0
        jobo

Hallo,

  
<script type="text/javascript">  
[code lang=javascript]  
var createColorObj;  
createColorObj = function (value, range) {  
    return {  
        "value": value,  
        "tmpValue" : value,  
        "range" : range,  
        "goDown" : true  
    };  
};  
var createColorHandler;  
createColorHandler = function (red, green, blue) {  
    return {  
        // second parameter is range in which color is to be changed  
        "red": createColorObj(red, 55),  
        "green": createColorObj(green, 10),  
        "blue": createColorObj(blue, 16),  
        getValue : function (thisObj, colorName) {  
            if (thisObj[colorName].tmpValue < thisObj[colorName].value - thisObj[colorName].range) {  
                thisObj[colorName].goDown = false;  
            }  
            if (thisObj[colorName].tmpValue > thisObj[colorName].value) {  
                thisObj[colorName].goDown = true;  
            }  
            if (thisObj[colorName].goDown) {  
                thisObj[colorName].tmpValue -= 1;  
            } else {  
                thisObj[colorName].tmpValue += 1;  
            }  
            return thisObj[colorName].tmpValue;  
        }  
    };  
};  
window.onload = function () {  
    var myBody, colorHandler, myBgColorChange;  
    myBody = document.getElementsByTagName("body")[0];  
    colorHandler = createColorHandler(255, 168, 136);  
    myBgColorChange = function () {  
        var red, green, blue;  
        red = colorHandler.getValue(colorHandler, "red");  
        green = colorHandler.getValue(colorHandler, "green");  
        blue = colorHandler.getValue(colorHandler, "blue");  
        myBody.style.backgroundColor = "RGB(" + red + "," + green + "," + blue + ")";  
    };  
    window.setInterval("myBgColorChange()", "120");  
};  

</script>
<body>
</body>
[/code]

Kriegt man das besser/übersichtlicher bzw. einfacher hin? Ich übergebe der Objektmethode getValue jetzt immer das eigene Objekt mit, denn "this" verweist ja durch setInterval dann bereits aufs Windows-Objekt, oder?

Sinn bzw. Spielerei ist, von RGB-Basiswerten in einem für jede Farbe unterschiedlichem Range die Farbe runter und wieder rauf und wieder runter etc.pp. wechseln zu lassen. Code funzt und passiert auch JSLint.
Gruß

jobo

  1. Kriegt man das besser/übersichtlicher bzw. einfacher hin? Ich übergebe der Objektmethode getValue jetzt immer das eigene Objekt mit, denn "this" verweist ja durch setInterval dann bereits aufs Windows-Objekt, oder?

    Das this von myBgColorChange, du willst ja aber this innerhalb von colorHandler.getValue und dort ist der Kontext colorHandler wie man sieht.

    1. Hallo,

      Kriegt man das besser/übersichtlicher bzw. einfacher hin? Ich übergebe der Objektmethode getValue jetzt immer das eigene Objekt mit, denn "this" verweist ja durch setInterval dann bereits aufs Windows-Objekt, oder?
      Das this von myBgColorChange, du willst ja aber this innerhalb von colorHandler.getValue und dort ist der Kontext colorHandler wie man sieht.

      Komisch, vorhin ging es im Browser mit FF allein mit "this". Dann ging es nicht, und ich habe mit thisObj und der Übergabe als Parameter gearbeitet.

      Jetzt geht es auch mit this. Was meinst du mit "wie man sieht"? Ich dachte jetzt, "this" bezöge sich immer auf den aufgerufenen Kontext?

      Das hier läuft grade bei mir im Broser:

        
      <script type="text/javascript">  
      var createColorObj;  
      createColorObj = function (value, range) {  
          return {  
              "value": value,  
              "tmpValue" : value,  
              "range" : range,  
              "goDown" : true  
          };  
      };  
      var createColorHandler;  
      createColorHandler = function (red, green, blue) {  
          return {  
              // second parameter is range in which color is to be changed  
              "red": createColorObj(red, 55),  
              "green": createColorObj(green, 10),  
              "blue": createColorObj(blue, 16),  
              getValue : function (colorName) {  
                  if (this[colorName].tmpValue < this[colorName].value - this[colorName].range) {  
                      this[colorName].goDown = false;  
                  }  
                  if (this[colorName].tmpValue > this[colorName].value) {  
                      this[colorName].goDown = true;  
                  }  
                  if (this[colorName].goDown) {  
                      this[colorName].tmpValue -= 1;  
                  } else {  
                      this[colorName].tmpValue += 1;  
                  }  
                  return this[colorName].tmpValue;  
              }  
          };  
      };  
      window.onload = function () {  
          var myBody, colorHandler, myBgColorChange;  
          myBody = document.getElementsByTagName("body")[0];  
          colorHandler = createColorHandler(255, 168, 136);  
          myBgColorChange = function () {  
              var red, green, blue;  
              red = colorHandler.getValue("red");  
              green = colorHandler.getValue("green");  
              blue = colorHandler.getValue("blue");  
              myBody.style.backgroundColor = "RGB(" + red + "," + green + "," + blue + ")";  
          };  
          myBgColorChange();  
          window.setInterval(myBgColorChange, "120");  
      };  
      </script>  
      <body>  
      </body>  
      
      

      Aber eben hatte ich auch     window.setInterval("myBgColorChange()", "120");
      und die Fehlerkonsole meint, myBgColorCange sei nicht definiert. Habe es umgeschrieben in     window.setInterval(myBgColorChange, "120"); und es ging. Keine Ahnung warum ???

      Gruß

      jobo

      1. Jetzt geht es auch mit this. Was meinst du mit "wie man sieht"? Ich dachte jetzt, "this" bezöge sich immer auf den aufgerufenen Kontext?

        der Kontext ist die Variable welche die Funktion aufruft und die steht vor dem .getValue.

        Aber eben hatte ich auch     window.setInterval("myBgColorChange()", "120");
        und die Fehlerkonsole meint, myBgColorCange sei nicht definiert. Habe es umgeschrieben in     window.setInterval(myBgColorChange, "120"); und es ging. Keine Ahnung warum ???

        myBgColorCange ist keine globale Funktion.

        1. Hallo,

          Jetzt geht es auch mit this. Was meinst du mit "wie man sieht"? Ich dachte jetzt, "this" bezöge sich immer auf den aufgerufenen Kontext?
          der Kontext ist die Variable welche die Funktion aufruft und die steht vor dem .getValue.

          ja, durch den Aufruf als Objektmethode:

            
          <script>  
          [code lang=javascript]  
          myObj = {  
              method : function () {  
                  alert(this);  
               }  
          };  
            
          function testThis() {  
              alert(this);  
          }  
          function callMyObjMethod() {  
              myObj.method();  
          }  
            
          testThis(); // [object Window]  
          callMyObjMethod(); // [object Object]  
          window.setTimeout(testThis,100); // [object Window]  
          window.setTimeout(callMyObjMethod,100); // [object Object]  
          window.onload = function () {  
              document.getElementById("callMyObjMethod").onclick = callMyObjMethod; // [object Object]  
              document.getElementById("callTestThis").onclick = testThis; // [object HTMLButtonElement]  
          }  
          
          

          </script>
          <body>
          <button id="callMyObjMethod">callMyObjMethod()</button>
          <button id="callTestThis">callTestThis()</button>
          </body>
          [/code]

          Aber eben hatte ich auch     window.setInterval("myBgColorChange()", "120");
          und die Fehlerkonsole meint, myBgColorCange sei nicht definiert. Habe es umgeschrieben in     window.setInterval(myBgColorChange, "120"); und es ging. Keine Ahnung warum ???
          myBgColorCange ist keine globale Funktion.

          Aber sie ist im window.onload definiert, genau wie auch setIntervall. Macht es denn einen Unterschied, welche der beiden Schreibweisen ich verwende? Für den Scope (Closure) doch wohl nicht, oder? Zumal es ja auch erst mit der Stringschreibweise ging ...;

          Gruß

          jobo

          1. Aber sie ist im window.onload definiert, genau wie auch setIntervall. Macht es denn einen Unterschied, welche der beiden Schreibweisen ich verwende? Für den Scope (Closure) doch wohl nicht, oder? Zumal es ja auch erst mit der Stringschreibweise ging ...;

            Doch, genau für die Closure macht es den Unterschied.
            Du hast im Prinzip

            var func = new Function("myBgColorChange()");  
            window.setInterval(func, 120);
            

            Aus deinem String wird eine neue globale Funktion mit dem String als Body definiert, diese kennt dann aber natürlich deine Closure nicht mehr, da es ja eine Funktion im globalen Scope ist.
            Das ist wie bei Events. Gibt man diese als String an, ist this windows. Gibt man sie als Funktionsreferenz an, ist this das Element.

            <script>  
              
            function func() {  
                alert(this);  
            }  
              
            window.onload = function () {  
                document.getElementById("test").onclick = func; // [object Object]  
            }  
              
            </script>  
            <body>  
            <button onclick="func()">[object Window]</button>  
            <button id="test">[object HTMLButtonElement]</button>  
            </body>  
            
            

            Im 1. Fall ist Element.onclick = function(){
            // this ist Element
              func(); // func wird im globalen Kontext gerufen
            }
            Im 2. Fall ist Element.onclick = func;
            Element.onclick() wird mit Kontext Element gerufen

            1. Hallo,

              Aber sie ist im window.onload definiert, genau wie auch setIntervall. Macht es denn einen Unterschied, welche der beiden Schreibweisen ich verwende? Für den Scope (Closure) doch wohl nicht, oder? Zumal es ja auch erst mit der Stringschreibweise ging ...;
              Doch, genau für die Closure macht es den Unterschied.
              Du hast im Prinzip

              var func = new Function("myBgColorChange()");

              window.setInterval(func, 120);

              
              > Aus deinem String wird eine neue globale Funktion mit dem String als Body definiert, diese kennt dann aber natürlich deine Closure nicht mehr, da es ja eine Funktion im globalen Scope ist.  
                
              Das leuchtet ein.  
                
              
              > Das ist wie bei Events. Gibt man diese als String an, ist this windows. Gibt man sie als Funktionsreferenz an, ist this das Element.  
              > ~~~javascript
              
              <script>  
              
              >   
              > function func() {  
              >     alert(this);  
              > }  
              >   
              > window.onload = function () {  
              >     document.getElementById("test").onclick = func; // [object Object]  
              > }  
              >   
              > </script>  
              > <body>  
              > <button onclick="func()">[object Window]</button>  
              > <button id="test">[object HTMLButtonElement]</button>  
              > </body>  
              > 
              
              

              Im 1. Fall ist Element.onclick = function(){
              // this ist Element
                func(); // func wird im globalen Kontext gerufen
              }
              Im 2. Fall ist Element.onclick = func;
              Element.onclick() wird mit Kontext Element gerufen

              Ok. das könnte man jetzt noch ergänzen mit dem Stringaufruf onclick="func2(this)", dann hätte man das "this" wieder eingefangen vom aufrufenden Element.

                
              <script>  
                
              function func() {  
                  alert(this);  
              }  
              function func2(callingElement) {  
                  alert(callingElement);  
              }  
                
              window.onload = function () {  
                  document.getElementById("test").onclick = func; // [object Object]  
              }  
                
              </script>  
              <body>  
              <button onclick="func()">[object Window]</button>  
              <button id="test">[object HTMLButtonElement]</button>  
              <button onclick="func2(this)">[object HTMLButtonElement]</button>  
              </body>  
              
              

              Frägt sich allerdings, warum da das "this" in dem String überhaupt als "this"-des-Elements interpretiert wird...;

              Gruß

              jobo

              1. Frägt sich allerdings, warum da das "this" in dem String überhaupt als "this"-des-Elements interpretiert wird...;

                Weil die generierte globale Funktion, welche deinen String als Function-Body enthält, als Element.onclick() aufgerufen wird.

                1. Hallo,

                  Frägt sich allerdings, warum da das "this" in dem String überhaupt als "this"-des-Elements interpretiert wird...;
                  Weil die generierte globale Funktion, welche deinen String als Function-Body enthält, als Element.onclick() aufgerufen wird.

                  Ja aber da muss doch intern erst noch der String zerlegt werden, dachte ich.
                  Rein von der Logik ist das schon klar und finde ich auch sinnig, dass this sich auf das aufrufende Objekt bezieht, in diesem Fall eben das HTML-Element.

                  Gruß

                  jobo

                  1. Ja aber da muss doch intern erst noch der String zerlegt werden, dachte ich.

                    Das verstehe ich nicht, der String wird natürlich irgendwann zur Laufzeit geparst und daraus eine Funktion erzeugt, dann ist es aber eine Funktion wie jede andere.

  2. Hi,

    Ich übergebe der Objektmethode getValue jetzt immer das eigene Objekt mit, denn "this" verweist ja durch setInterval dann bereits aufs Windows-Objekt, oder?

    Auch auf diese Problematik geht der Artikel http://aktuell.de.selfhtml.org/artikel/javascript/organisation/ ein.

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Hallo,

      Hi,

      Ich übergebe der Objektmethode getValue jetzt immer das eigene Objekt mit, denn "this" verweist ja durch setInterval dann bereits aufs Windows-Objekt, oder?

      Auch auf diese Problematik geht der Artikel http://aktuell.de.selfhtml.org/artikel/javascript/organisation/ ein.

      MfG ChrisB

      Ja, eigentlich kenne ich den Artikel. Wobei ich zwei Sachen nicht ganz glücklich finde mittlerweile:

      "Lösung: this vermeiden

      Eine mögliche Lösung ist, das Object immer explizit über dessen Namen anzusprechen anstatt über this.

      this wird dann nur noch in Methoden verwendet, die als Event-Handler dienen. Denn this ist die einzige Möglichkeit, im Internet Explorer auf das Element zuzugreifen, dessen Handler das Ereignis ausgelöst hat. In Browsern, die dem DOM-Events-Standard folgen, gibt es dafür die Eigenschaft currentTarget des Event-Objektes."

      Es ist vielleicht nicht so sinnig, Objektmethoden direkt an Eventhandler zu knüpfen?

      " // Fehler: this verweist auf das Element, dem der Event-Handler anhängt"

      Das ist aus meiner Sicht kein Fehler, sondern logisch.

      Und es geht ja auch mit this und setIntervall, wenn die aufgerufene Funktion nicht direkt die Objektmethode ist, sondern diese aufruft: https://forum.selfhtml.org/?t=209455&m=1425528.

      Ob mein Code noch sinniger gestaltbar ist, weiß ich allerdings nicht.

      Gruß

      jobo

      1. Hi,

        Und es geht ja auch mit this und setIntervall, wenn die aufgerufene Funktion nicht direkt die Objektmethode ist, sondern diese aufruft: https://forum.selfhtml.org/?t=209455&m=1425528.

        Ob mein Code noch sinniger gestaltbar ist, weiß ich allerdings nicht.

        http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#closures-anwendung

        Referenz auf this im Objekt zwischenspeichern, und anschließend diese statt dem (im Aufrufkontext dann "anderen") this verwenden.

        MfG ChrisB

        --
        RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
        1. Hallo,

          Hi,

          Und es geht ja auch mit this und setIntervall, wenn die aufgerufene Funktion nicht direkt die Objektmethode ist, sondern diese aufruft: http://forum.de.selfhtml.org/my/?t=209455&m=1425528.

          Ob mein Code noch sinniger gestaltbar ist, weiß ich allerdings nicht.

          http://aktuell.de.selfhtml.org/artikel/javascript/organisation/#closures-anwendung

          Referenz auf this im Objekt zwischenspeichern, und anschließend diese statt dem (im Aufrufkontext dann "anderen") this verwenden.

          Das "new" versuche ich zu umgehen und notiere deshalb das Objekt als Literal (wie von Crockford empfohlen). Da klappt das mit dem that = this; nicht ...;

          Gruß

          jobo

          1. Das "new" versuche ich zu umgehen

            Sonderlich geholfen hat dir der Verzicht auf Konstruktoren bei der Organisation deines Codes anscheinend nicht.

            und notiere deshalb das Objekt als Literal (wie von Crockford empfohlen). Da klappt das mit dem that = this; nicht ...;

            Das Prinzip sind Closures, dazu brauchst du nicht this, sondern einfach eine Referenz auf das Objekt.

            function makeFoo () {  
              var foo = {  
                func: function () {  
                   alert(foo);  
                }  
              };  
              return foo;  
            }  
            setTimeout(makeFoo().func, 1);
            

            Mathias

            1. Hallo,

              Das "new" versuche ich zu umgehen

              Sonderlich geholfen hat dir der Verzicht auf Konstruktoren bei der Organisation deines Codes anscheinend nicht.

              Naja, wenn ich nicht weiß, wie das Prinzip umsetzen? Ich habe zwei Objekte, die jede mittels eine Funktion generiert werden. Ein Farbobjekt mit vier Eigenschaften und eine Farbverwaltung, die drei Instanzen des Farbobjektes (rot, grün, blau) beinhaltet sowie die Methode, den aktuellen Farbwert zu ändern für jede Farbe.

              In der window.onload-Funktion ist die Instanz des Farbverwalters geclosured und deshalb für die Funktion, die die Farbe ändert, zugänglich, da diese in der window.onload-Funktion definiert wird.

              Ob das Prinzip sinnig ist oder optierungsfähig weiß ich immer noch nicht. Das "new" brauche ich dabei eigentlich sowieso nicht.

              und notiere deshalb das Objekt als Literal (wie von Crockford empfohlen). Da klappt das mit dem that = this; nicht ...;

              Das Prinzip sind Closures, dazu brauchst du nicht this, sondern einfach eine Referenz auf das Objekt.

              function makeFoo () {

              var foo = {
                  func: function () {
                     alert(foo);
                  }
                };
                return foo;
              }
              setTimeout(makeFoo().func, 1);

                
              Genau, die Referenz auf die Farbverwaltung (colorHandler = createColorHandler(255, 168, 136);) habe ich doch dann in der Funktion "myBgColorChange", oder?  
                
              Gruß  
                
              jobo
              
      2. "Lösung: this vermeiden

        Eine mögliche Lösung ist, das Object immer explizit über dessen Namen anzusprechen anstatt über this.

        this wird dann nur noch in Methoden verwendet, die als Event-Handler dienen. Denn this ist die einzige Möglichkeit, im Internet Explorer auf das Element zuzugreifen, dessen Handler das Ereignis ausgelöst hat. In Browsern, die dem DOM-Events-Standard folgen, gibt es dafür die Eigenschaft currentTarget des Event-Objektes."

        Es ist vielleicht nicht so sinnig, Objektmethoden direkt an Eventhandler zu knüpfen?

        Diese Erwiderung verstehe ich nicht. Meinst du, man sollte Objektmethoden nicht als Event-Handler verwenden? Wieso?

        " // Fehler: this verweist auf das Element, dem der Event-Handler anhängt"

        Das ist aus meiner Sicht kein Fehler, sondern logisch.

        »Fehler« bezieht sich hier darauf, dass der Code nicht das erwartete tut.

        Logisch ist es natürlich, dass jeder Event-Handler im Kontext des Elements ausgeführt wird – wobei man das für Event-Handling längst nicht braucht, siehe oben.

        Mathias

        1. Hallo,

          "Lösung: this vermeiden

          Eine mögliche Lösung ist, das Object immer explizit über dessen Namen anzusprechen anstatt über this.

          this wird dann nur noch in Methoden verwendet, die als Event-Handler dienen. Denn this ist die einzige Möglichkeit, im Internet Explorer auf das Element zuzugreifen, dessen Handler das Ereignis ausgelöst hat. In Browsern, die dem DOM-Events-Standard folgen, gibt es dafür die Eigenschaft currentTarget des Event-Objektes."

          Es ist vielleicht nicht so sinnig, Objektmethoden direkt an Eventhandler zu knüpfen?

          Diese Erwiderung verstehe ich nicht. Meinst du, man sollte Objektmethoden nicht als Event-Handler verwenden? Wieso?

          Nun ja, dann ist das Objekt wohl eher ein Namespace für eine Methodensammlung, die mit Eventhandlern verknüpft werden. Ich dachte halt, wenn "this" da zu Verwirrungen führt ist es vielleicht "falsch", dort mit "this" auf das Objekt zu verweisen, obwohl doch schon klar ist, dass das Objekt nur als Funktionsträger für Events fungiert. Aber vermutlich, wenn du das so schreibst, wird das so nicht praktiziert.

          " // Fehler: this verweist auf das Element, dem der Event-Handler anhängt"

          Das ist aus meiner Sicht kein Fehler, sondern logisch.

          »Fehler« bezieht sich hier darauf, dass der Code nicht das erwartete tut.

          Naja, das kommt drauf an, wer was erwarten. Paul fragt Martin: "wer ist meines Vaters Sohn und doch nicht mein Bruder?" Martin weiß es nicht. Paul: "na ich!". Martin geht zu Sonja und sagt: "Du kennst Du schon den: wer ist meines Vaters Sohn und doch nicht mein Bruder?". Sonja: "na Du!". Martin: "nee, Paul". "Ich" (also this) bezieht sich doch immer auf den, der es ausspricht. Wenn ich einem Eventhandler (deshalb sagte ich ja oben auch, das wäre "falsch") eine Methode eines anderen Objektes anhänge, dann ist "ich" natürlich und auch logischerweise und erwarteter Weise "ich"/this. Nur im Kontext des Codes geht es unter oder wird falsch interpretiert, weil nicht klar ist Verwirrung herrscht, wem der Code nun zugeordnet wird, welchem Objekt.

          Logisch ist es natürlich, dass jeder Event-Handler im Kontext des Elements ausgeführt wird – wobei man das für Event-Handling längst nicht braucht, siehe oben.

          Ich dachte IE braucht das? Wieder was nicht verstanden, vielleicht doch schon zu spät heute ...;

          Gruß

          jobo

          1. Meinst du, man sollte Objektmethoden nicht als Event-Handler verwenden? Wieso?

            Nun ja, dann ist das Objekt wohl eher ein Namespace für eine Methodensammlung, die mit Eventhandlern verknüpft werden.

            Objekte, vor allem in JavaScript, sind immer Namespaces für Methoden sowie Status-Variablen.

            Ich dachte halt, wenn "this" da zu Verwirrungen führt ist es vielleicht "falsch", dort mit "this" auf das Objekt zu verweisen, obwohl doch schon klar ist, dass das Objekt nur als Funktionsträger für Events fungiert.

            Ein Objekt kann zur bloßen Gruppierung von Methoden genutzt werden. In der Regel speichert man dort aber einen bestimmten State. Die Methoden ändern diesen State oder geben ihn aus. Es ergibt daher Sinn, dass die Methoden für Event-Handling, also Eingabe, und DOM Scripting, also Ausgabe genutzt werden.

            Aber vermutlich, wenn du das so schreibst, wird das so nicht praktiziert.

            Man kann natürlich durchaus eine Abstraktionsschicht einbauen, die die Aufgaben trennt, zum Beispiel Model-View-Controller. Damit würden Event-Handler nicht direkt die Daten ändern.

            Nur im Kontext des Codes geht es unter oder wird falsch interpretiert, weil nicht klar ist Verwirrung herrscht, wem der Code nun zugeordnet wird, welchem Objekt.

            Function Binding bzw. die Nutzung von call und apply widmet sich genau diesem Problem, indem die Funktion einem bestimmten Objekt zugeordnet wird und diese Zuordnung bei sämtlichen Aufrufen beibehalten wird.

            Logisch ist es natürlich, dass jeder Event-Handler im Kontext des Elements ausgeführt wird – wobei man das für Event-Handling längst nicht braucht, siehe oben.

            Ich dachte IE braucht das? Wieder was nicht verstanden, vielleicht doch schon zu spät heute ...;

            Wenn man im IE < 9 auf e.currentTarget zugreifen will, dann benötigt man das ursprüngliche this. Ansonsten kann man den Handler an ein anderes Objekt binden, wie man lustig ist.

            Mathias

            1. Hallo,

              Meinst du, man sollte Objektmethoden nicht als Event-Handler verwenden? Wieso?

              Nun ja, dann ist das Objekt wohl eher ein Namespace für eine Methodensammlung, die mit Eventhandlern verknüpft werden.

              Objekte, vor allem in JavaScript, sind immer Namespaces für Methoden sowie Status-Variablen.

              Dann habe ich das jetzt mal alles in eine eigenes Objekt verpackt, um den allgemeinen Namensraum nicht zu verschmutzen. Und definiere im Timeout eine Funktion, die eine Objektmethode aufruft, um das "this" korrekt zu erhalten:

                
              <script type="text/javascript">  
              [code lang=javascript]  
              var MyBgColorChanger;  
              MyBgColorChanger = {  
                  red : false,  
                  green : false,  
                  blue : false,  
                  bgElem : false,  
                  createColorObj : function (value, range) {  
                      return {  
                          "value": value,  
                          "tmpValue" : value,  
                          "range" : range,  
                          "goDown" : true  
                      };  
                  },  
                  init : function (bgElem, redVal, greenVal, blueVal) {  
                      this.bgElem = bgElem;  
                      this.red = this.createColorObj(redVal, 55);  
                      this.green = this.createColorObj(greenVal, 10);  
                      this.blue = this.createColorObj(blueVal, 16);  
                  },  
                  getValue : function (colorName) {  
                      if (this[colorName].tmpValue < this[colorName].value - this[colorName].range) {  
                          this[colorName].goDown = false;  
                      }  
                      if (this[colorName].tmpValue > this[colorName].value) {  
                          this[colorName].goDown = true;  
                      }  
                      if (this[colorName].goDown) {  
                          this[colorName].tmpValue -= 1;  
                      } else {  
                          this[colorName].tmpValue += 1;  
                      }  
                      return this[colorName].tmpValue;  
                  },  
                  bgColorChange : function () {  
                      var red, green, blue;  
                      red = this.getValue("red");  
                      green = this.getValue("green");  
                      blue = this.getValue("blue");  
                      this.bgElem.style.backgroundColor = "RGB(" + red + "," + green + "," + blue + ")";  
                  }  
              };  
                
              window.onload = function () {  
                  var myBgElem;  
                  myBgElem = document.getElementsByTagName("body")[0];  
                  MyBgColorChanger.init(myBgElem, 255, 168, 136);  
                  window.setInterval(function () {MyBgColorChanger.bgColorChange(); }, "120");  
              };  
              
              

              </script>
              <body>
              </body>

              [/code]

              Gruß

              jobo

              1. Hallo,

                bzw. hier noch die Konfiguration von Startwert und Range, in dem die jeweilige Farbe variieren soll als Objekt-Parameter an die Funktion übergeben:

                  
                var MyBgColorChanger;  
                MyBgColorChanger = {  
                    red : false,  
                    green : false,  
                    blue : false,  
                    bgElem : false,  
                    createColorObj : function (value, range) {  
                        return {  
                            "value": value,  
                            "tmpValue" : value,  
                            "range" : range,  
                            "goDown" : true  
                        };  
                    },  
                    init : function (bgElem, red, green, blue) {  
                        this.bgElem = bgElem;  
                        this.red = this.createColorObj(red.start, red.range);  
                        this.green = this.createColorObj(green.start, green.range);  
                        this.blue = this.createColorObj(blue.start, blue.range);  
                    },  
                    getValue : function (colorName) {  
                        if (this[colorName].tmpValue < this[colorName].value - this[colorName].range) {  
                            this[colorName].goDown = false;  
                        } else if (this[colorName].tmpValue > this[colorName].value) {  
                            this[colorName].goDown = true;  
                        }  
                        if (this[colorName].goDown) {  
                            this[colorName].tmpValue -= 1;  
                        } else {  
                            this[colorName].tmpValue += 1;  
                        }  
                        return this[colorName].tmpValue;  
                    },  
                    bgColorChange : function () {  
                        var red, green, blue;  
                        red = this.getValue("red");  
                        green = this.getValue("green");  
                        blue = this.getValue("blue");  
                        this.bgElem.style.backgroundColor = "RGB(" + red + "," + green + "," + blue + ")";  
                    }  
                };  
                  
                window.onload = function () {  
                    var myBgElem;  
                    myBgElem = document.getElementsByTagName("body")[0];  
                    MyBgColorChanger.init(myBgElem, {start : 255, range : 55}, {start : 168, range : 10}, {start : 136, range : 16});  
                    window.setInterval(function () {MyBgColorChanger.bgColorChange(); }, "120");  
                };  
                
                

                Gruß

                jobo

                1. Dann habe ich das jetzt mal alles in eine eigenes Objekt verpackt, um den allgemeinen Namensraum nicht zu verschmutzen. Und definiere im Timeout eine Funktion, die eine Objektmethode aufruft, um das "this" korrekt zu erhalten:

                  Weil du ja die Objektorientierung ins Spiel gebracht hat, könnte man jetzt einwenden, daß in diesem Fall eigentlich nur bgColorChange-Methode nach aussen sichtbar sein sollte, da alles andere eigentlich interne States sind.
                  Am Ende kann man dann auf ein eigenes Objekt verzichten. ;-)

                  function createColorHandler(elem, prop, red, redRange, green, greenRange, blue, blueRange) {  
                      function createColorObj(v, r) {  
                        var value = v;  
                        var max = v;  
                        var range = r;  
                        var dir = 1;  
                        return function() {  
                          if (value <= max - range || value >= max) {  
                            dir *= -1;  
                          }  
                          value += dir;  
                          return value;  
                        };  
                      }  
                      var red = createColorObj(red, redRange);  
                      var green = createColorObj(green, greenRange);  
                      var blue = createColorObj(blue, blueRange);  
                      return function() {  
                        elem[prop] = "RGB(" + red() + "," + green() + "," + blue() + ")";  
                      };  
                  };  
                  window.onload = function () {  
                      var myBody = document.getElementsByTagName("body")[0];  
                      window.setInterval(createColorHandler(myBody.style, "backgroundColor", 255, 55, 168, 10, 136, 16), 120);  
                  };
                  
                  1. Hallo,

                    Dann habe ich das jetzt mal alles in eine eigenes Objekt verpackt, um den allgemeinen Namensraum nicht zu verschmutzen. Und definiere im Timeout eine Funktion, die eine Objektmethode aufruft, um das "this" korrekt zu erhalten:

                    Weil du ja die Objektorientierung ins Spiel gebracht hat, könnte man jetzt einwenden, daß in diesem Fall eigentlich nur bgColorChange-Methode nach aussen sichtbar sein sollte, da alles andere eigentlich interne States sind.
                    Am Ende kann man dann auf ein eigenes Objekt verzichten. ;-)

                    function createColorHandler(elem, prop, red, redRange, green, greenRange, blue, blueRange) {

                    function createColorObj(v, r) {
                          var value = v;
                          var max = v;
                          var range = r;
                          var dir = 1;
                          return function() {
                            if (value <= max - range || value >= max) {
                              dir *= -1;
                            }
                            value += dir;
                            return value;
                          };
                        }
                        var red = createColorObj(red, redRange);
                        var green = createColorObj(green, greenRange);
                        var blue = createColorObj(blue, blueRange);
                        return function() {
                          elem[prop] = "RGB(" + red() + "," + green() + "," + blue() + ")";
                        };
                    };
                    window.onload = function () {
                        var myBody = document.getElementsByTagName("body")[0];
                        window.setInterval(createColorHandler(myBody.style, "backgroundColor", 255, 55, 168, 10, 136, 16), 120);
                    };

                      
                    Macht es aber Sinn, den colorHandler immer wieder neu zu kreiren/createn? Kann es grad nich testen, aber werden dadurch Werte nicht wieder überschrieben? Ansonsten höre ich Crockford sagen: "JS is about functions". Hatte hier mal seine Memoizer-Funktion im Forum platziert: <http://forum.de.selfhtml.org/archiv/2011/5/t204981/#m1388909>. Und in dem Sinne aus meiner Sicht: Ist auf jeden Fall eine sehr feine Optimierung!  
                      
                    Gruß  
                      
                    jobo
                    
                    1. Hallo,

                      Macht es aber Sinn, den colorHandler immer wieder neu zu kreiren/createn? Kann es grad nich testen, aber werden dadurch Werte nicht wieder überschrieben?

                      Also doch kurz Zeit gehabt: Im setIntervall wird ja die Funktion colorHandler nur genau einmal aufgerufen, nämlich um die Funktion zu erzeugen, die setIntervall dann immer wieder aufrufen soll. Habe es noch JSLint-konform gemacht und musste dafür die doppelt-Definierten Farbvariablennamen ändern, hoffentlich sinnig von "red" in "nextRed" ...;

                        
                      function createColorHandler(elem, prop, red, redRange, green, greenRange, blue, blueRange) {  
                          function createColorObj(v, r) {  
                              var value = v, max = v, range = r, dir = 1;  
                              return function () {  
                                  if (value <= max - range || value >= max) {  
                                      dir *= -1;  
                                  }  
                                  value += dir;  
                                  return value;  
                              };  
                          }  
                          var nextRed = createColorObj(red, redRange),  
                              nextGreen = createColorObj(green, greenRange),  
                              nextBlue = createColorObj(blue, blueRange);  
                          return function () {  
                              elem[prop] = "RGB(" + nextRed() + "," + nextGreen() + "," + nextBlue() + ")";  
                          };  
                      }  
                        
                      window.onload = function () {  
                          var myBody = document.getElementsByTagName("body")[0];  
                          window.setInterval(createColorHandler(myBody.style, "backgroundColor", 255, 55, 168, 10, 136, 16), 120);  
                      };  
                      
                      

                      Gruß

                      jobo

                      1. Hallo,

                        statt (elem, prop, red, redRange, green, greenRange, blue, blueRange)

                        vielleicht eher (style, colorProp, rgb, rgbRanges)?

                        mit

                        rgb = [255, 168,136]; rgbRanges = [55, 10, 16];

                        Gruß

                        jobo

                        1. Hallo,

                          sähe dann so aus:

                            
                          function createColorHandler(style, colorProp, rgb, rgbRanges) {  
                              function createColorObj(v, r) {  
                                  var value = v, max = v, range = r, dir = 1;  
                                  return function () {  
                                      if (value <= max - range || value >= max) {  
                                          dir *= -1;  
                                      }  
                                      value += dir;  
                                      return value;  
                                  };  
                              }  
                              var nextRed = createColorObj(rgb[0], rgbRanges[0]),  
                                  nextGreen = createColorObj(rgb[1], rgbRanges[1]),  
                                  nextBlue = createColorObj(rgb[2], rgbRanges[2]);  
                              return function () {  
                                  style[colorProp] = "RGB(" + nextRed() + "," + nextGreen() + "," + nextBlue() + ")";  
                              };  
                          }  
                            
                          window.onload = function () {  
                              var myBody = document.getElementsByTagName("body")[0];  
                              window.setInterval(createColorHandler(myBody.style, "backgroundColor", [255, 168, 136], [55, 10, 16]), 120);  
                          };
                          

                          Gruß

                          jobo

                          1. Hallo,

                            Hallo,

                            sähe dann so aus:

                            function createColorHandler(style, colorProp, rgb, rgbRanges) {
                            };

                              
                            Da "style" ja ein reserviertes Wort ist (s. Syntaxhighlight) vielleicht besser "elemStyle" ...;  
                              
                            Macht es grundsätzlich Sinn, Code so im Detail zu refactorieren? (Vorausgesetzt, das wäre eine Verbesserung?)  
                              
                            Gruß  
                              
                            jobo
                            
                            1. Da "style" ja ein reserviertes Wort ist

                              Ist es nicht.
                              Das Syntaxhighlighting hier hebt allgemein bekannte Identifier, Schlüsselwörter sowie reservierte Wörter hervor.

                              Mathias

                              1. Hallo,

                                Da "style" ja ein reserviertes Wort ist

                                Ist es nicht.
                                Das Syntaxhighlighting hier hebt allgemein bekannte Identifier, Schlüsselwörter sowie reservierte Wörter hervor.

                                Du würdest eher das Element übergeben, als elemStyle?

                                Mathias

                                Gruß

                                jobo

                                1. Du würdest eher das Element übergeben, als elemStyle?

                                  Ja, natürlich. Bei sämtlichen DOM-Operationen ist das Element zentral. Ich übergebe ja auch kein Attributknoten, wenn ich eine Helferfunktion habe, die Attributwerte ändert. Die Kompetenz, vom Element auf das Inline-Style-Objekt zu kommen, sofern es dieses benötigt, stehe ich dem Modul zu. Es ist sogar besser aus Sicht der Kapselung, bloß das Element zu übergeben, weil der Code, der das Modul aufruft nicht wissen sollte, mit welchen Unterobjekten die konkrete Umsetzung hantiert. Das kann sich jederzeit auch ändern, es muss nicht zwangsläufig style sein.

                                  Mathias

                          2. var myBody = document.getElementsByTagName("body")[0];
                                window.setInterval(createColorHandler(myBody.style, "backgroundColor", [255, 168, 136], [55, 10, 16]), 120);

                            Was ich schreiben ist eher so etwas:

                            cycleColors({ element: document.body, property: 'backgroundColor', from: [255, 168, 136], to: [55, 10, 16], duration: 3000 });

                            Mathias

                            1. Hallo,

                              var myBody = document.getElementsByTagName("body")[0];
                                  window.setInterval(createColorHandler(myBody.style, "backgroundColor", [255, 168, 136], [55, 10, 16]), 120);

                              Was ich schreiben ist eher so etwas:

                              cycleColors({ element: document.body, property: 'backgroundColor', from: [255, 168, 136], to: [55, 10, 16], duration: 3000 });

                              Die Duration muss doch aber als Paramter ins setIntervall ?
                              Gruß

                              jobo

                              1. Die Duration muss doch aber als Paramter ins setIntervall ?

                                Was er hier vorschlägt geht viel weiter als dein konkretes Beispiel. Er redet von einem algemeingültigem Tweening-Objekt (der name cycleColors ist vielleicht nicht ganz passend ;-)

                                1. Hallo,

                                  Die Duration muss doch aber als Paramter ins setIntervall ?

                                  Was er hier vorschlägt geht viel weiter als dein konkretes Beispiel. Er redet von einem algemeingültigem Tweening-Objekt (der name cycleColors ist vielleicht nicht ganz passend ;-)

                                  Naja, 1. ist das ja kein richtiges Tweening, oder? Sondern das simple Durchlaufen einer Reihe. Und 2. wäre es nicht sinnvoll, erstmal das konkrete Beispiel beispielhaft zu optimieren um es dann im zweiten Schritt zu verallgemeinern. Das zu Grunde liegende Konzept ist doch das selbe bzw. falls es das ist ...; Mich würde interessieren, was ich an meinem Ansatz ändern sollte bzw. wo ich ansetzen sollte ...;

                                  Gruß

                                  jobo

                                  1. Naja, 1. ist das ja kein richtiges Tweening, oder? Sondern das simple Durchlaufen einer Reihe.

                                    Das ist der einfachste Fall.

                                    Und 2. wäre es nicht sinnvoll, erstmal das konkrete Beispiel beispielhaft zu optimieren um es dann im zweiten Schritt zu verallgemeinern.

                                    Kommt darauf an, wenn du erstmal denkst, mit dem konkreten Fall auf lange Sicht hinzukommen, lohnt sich keine Verallgemeinerung.
                                    Ist von Anfang an abzusehen, dass weitere Fälle mit einer Verallgemeinerung erschlagen werden können, muss man nicht erst den Spezialfall implementieren.

                                2. Hallo,

                                  Die Duration muss doch aber als Paramter ins setIntervall ?

                                  Was er hier vorschlägt geht viel weiter als dein konkretes Beispiel. Er redet von einem algemeingültigem Tweening-Objekt (der name cycleColors ist vielleicht nicht ganz passend ;-)

                                  Das API-Beispiel war ein Beispiel für diesen konkreten Anwendungsfall. Hinter der API würde sich genau die Funktionalität verstecken, die der Code jetzt schon bietet (inklusive dem setInterval eben). Dabei ging es doch um das Durchlaufen von Farben, oder habe ich das falsch verstanden? Die Duration ergibt tatsächlich keinen Sinn, wenn das ganze unendlich hin- und herlaufen soll.

                                  Allgemeines Tweening wäre nochmal eine Stufe weiter, das hatte ich erst einmal nicht im Sinn.

                                  Mathias

                                  1. Das API-Beispiel war ein Beispiel für diesen konkreten Anwendungsfall. Hinter der API würde sich genau die Funktionalität verstecken, die der Code jetzt schon bietet (inklusive dem setInterval eben).

                                    Ich sträube mich ein wenig hier gleich von API zu reden, das ist meines Erachtens min. eine Ebene höher.

                                    Dabei ging es doch um das Durchlaufen von Farben, oder habe ich das falsch verstanden?

                                    Eigentlich geht es um alles und nichts. Die Ausgangsfrage war der Kontext von colorHandler.getValue, dann ging es über den Scope globaler Funktionen zu der Syntax beim Zugriff auf Objekteigenschaften und schließlich zur Definition eines Objektes mit einer Schnittstelle welche zyklisch aufgerufen wird.
                                    Jetzt sind wir bei der Definition einer API zum Farbwechsel?

                                    Allgemeines Tweening wäre nochmal eine Stufe weiter, das hatte ich erst einmal nicht im Sinn.

                                    Dann habe ich dich falsch verstanden.

                  2. Weil du ja die Objektorientierung ins Spiel gebracht hat, könnte man jetzt einwenden, daß in diesem Fall eigentlich nur bgColorChange-Methode nach aussen sichtbar sein sollte, da alles andere eigentlich interne States sind.
                    Am Ende kann man dann auf ein eigenes Objekt verzichten. ;-)

                    Man kann viel, einen wirklichen Grund dafür gibt es nicht. Diesen Code finde ich ziemlich unlesbar und unverständlich. Eine klassische OOP-Lösung, die mit tatsächlichen Objekten arbeitet, würde ich hier vorziehen.

                    function createColorHandler(elem, prop, red, redRange, green, greenRange, blue, blueRange) {

                    createColorHandler ist ein ziemlich unpassender Name. Zurückgegeben wird ja eine Step-Funktion für eine Farb-Animation. Wieso nicht gleich die Animation als ganze wegkapseln?

                    function createColorObj(v, r) {
                          var value = v;
                          var max = v;
                          var range = r;
                          var dir = 1;
                          return function() {
                            if (value <= max - range || value >= max) {
                              dir *= -1;
                            }
                            value += dir;
                            return value;
                          };
                        }

                    Hier wird kein Objekt erzeugt, sondern eine Closure. Kein Problem an sich, aber createColorObj ist kein passender Name, eher createNextColorFunc oder so.

                    Allgemein: Kapselung in der Programmierung ist [link:http://molily.de/js/organisation-instanzen.html#kapselung@title=kein Selbstzweck] und hat auch nichts mit von außen effektiv nicht sichtbaren Interna zu tun. Kapselung soll einem ermöglichen, Programme zu strukturieren und sinnvolle Schnittstellen anzubieten, um die Schnittstelle von der Implementierung zu trennen. Konkret, nur weil man Closures hat, muss man nicht sämtlichen State in Closures kapseln.

                    var red = createColorObj(red, redRange);

                    Eine Funktion namens »red«? Sollte zumindest [pref:t=209455;m=1425820@title=nextRead] heißen.

                    window.setInterval(createColorHandler(myBody.style, "backgroundColor", 255, 55, 168, 10, 136, 16), 120);
                    };

                      
                    Animationen kann man sehr schön objektorientiert lösen und abstrahieren. Dafür gibt es viele gute Beispiele. Dies hingegen ist m.E. keine schöne und lesbare API, ich würde sie nicht benutzen wollen.  
                      
                    Vielleicht sollte jobo erst einmal versuchen, einfachen, klassischen OO-Code zu schreiben, verständliche APIs zu entwerfen und dann stärker funktional zu programmieren. Denn diesen Code finde ich alles andere als elegant.  
                      
                    Mathias
                    
                    1. createColorHandler ist ein ziemlich unpassender Name. Zurückgegeben wird ja eine Step-Funktion für eine Farb-Animation.

                      Die aber nichts anderes als ein Handler für ein Timerevent ist.

                      aber createColorObj ist kein passender Name, eher createNextColorFunc

                      ja, (bis auf das next vielleicht, aber darüber kann man streiten)

                      Wieso nicht gleich die Animation als ganze wegkapseln?

                      So würde man das sicherlich lösen, wenn es die Aufgabe gewesen wäre.

                      Allgemein: Kapselung in der Programmierung ist kein Selbstzweck

                      Bis hier stimme ich dir noch zu.

                      und hat auch nichts mit von außen effektiv nicht sichtbaren Interna zu tun.

                      Doch! Genau das ist der Sinn!

                      Eine Funktion namens »red«? Sollte zumindest nextRead heißen.

                      red finde ich eigentlich ganz passend, es gibt den Rotanteil wieder, von daher sollte das Funktionsargument redMax heißen, m. M. n., aber die Bezeichner sind Geschmackssache.

                      1. Hallo,

                        und hat auch nichts mit von außen effektiv nicht sichtbaren Interna zu tun.
                        Doch! Genau das ist der Sinn!

                        Noch einmal die Links, die ich bereits gepostet habe:
                        http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/#encapsulation
                        http://molily.de/js/organisation-instanzen.html#kapselung

                        Sprachen wie Ruby und Python haben einfach keine effektive Kapselung. Soweit ich weiß, gibt es bei C# und Java ebenfalls eine Möglichkeit, die Kapselung zu umgehen (Wikipedia). Ich finde gerade den Thread nicht wieder, wo wir das schon einmal hier diskutiert haben.

                        Vor allem bei Ruby und Python ist es ein echtes Feature, dass private Methoden und Eigenschaften in Sonderfällen von außen zugänglich sind. Das widerspricht der Kapselung nicht grundsätzlich oder stellt ihre allgemeinen Nützlichkeit infrage.

                        red finde ich eigentlich ganz passend, es gibt den Rotanteil wieder, von daher sollte das Funktionsargument redMax heißen, m. M. n., aber die Bezeichner sind Geschmackssache.

                        Ja, wenn es den Rotanteil herausgeben würde, den man beim Erzeugen hineingegeben hat. Allerdings gibt sie erstens einen veränderten Wert zurück und ändert zudem den gespeicherten, sie ist also nicht »pure«.

                        Mathias

                        1. Vor allem bei Ruby und Python ist es ein echtes Feature, dass private Methoden und Eigenschaften in Sonderfällen von außen zugänglich sind. Das widerspricht der Kapselung nicht grundsätzlich oder stellt ihre allgemeinen Nützlichkeit infrage.

                          <ins>nicht</ins>

                          1. Noch einmal die Links, die ich bereits gepostet habe:

                            Selbst dort finde ich "The main reason is that a programmer himself wants to get access to the encapsulated (please notice, I’m specifically not using term “hidden”) data. And if these data will be somehow incorrectly changed or there will be any error — the full responsibility for this is completely on the programmer, but not simply a “typing error” or “someone has casually changed some field”. But if such cases become frequent, we may nevertheless note a bad programming practice and style, since usually it’s the best to “talk” with objects only via public API." womit eigentlich alles gesagt ist.
                            Und meine Persönliche Erfahrung sagt mir, daß auf alles, was nicht gekapselt ist, auch aus irgendeinem Grund jemand zugreift.
                            Dann wird ein Balkon nach dem anderen an ein Objekt gebaut. Sind die Daten gekapselt, muss jemand der darauf Zugriff haben möchte mit dem Entwickler reden. Dann kann man zusammen entscheiden, ob es sinnvoll ist diese in der Schnittstelle nach außen zu geben, oder ob derjenige nicht eigentlich versucht eine Funktionalität außen rum zu frickeln, die eigentlich an das Objekt gehört. Nur als ein Beispiel.

                            Sprachen wie Ruby und Python haben einfach keine effektive Kapselung.

                            Das mag sein, ist dann aber eine Schwachstelle der Sprache.

                            Soweit ich weiß, gibt es bei C# und Java ebenfalls eine Möglichkeit, die Kapselung zu umgehen (Wikipedia).

                            Ich weiß es nicht, aber da dort auch das C++ friend mit in der Liste steht, bin ich skeptisch, daß man damit wirklich von außen Zugriff auf gekapselte Daten bekommt. Gerade friend im C++ ist ja nicht dazu da, die Kapselung zu umgehen, sondern sie zu erhöhen, indem eine Methode nicht öffentlich gemacht werden muß, sondern einem speziellen Objekt Zugriff auf die Interna gestattet wird. Das ist auch nicht gut und auch immer anders lösbar, aber ein Kompromiss den man eingehen kann um größere Umstruckturierungen zu vermeiden, weil die Zeit fehlt.

                            Nehmen wir doch mal dieses Beispiel
                            init ist klar, die benötigt man in der einen oder anderen Art.
                            bgColorChange auch
                            createColorObj erzeugt Objekte die nur intern gebraucht werden. Wozu soll diese von außen zugreifbar sein?
                            getValue, da ist es sogar gefährlich diese nach außen zu legen, da diese den Wert für den aktuellen Schritt berechnet und jeder weitere Zugriff hier den Ablauf durcheinander bringen würde.
                            red, green, blue und bgElem sind eindeutig interne Daten und gehen keinen etwas an

                            1. Hallo,

                              Nehmen wir doch mal dieses Beispiel
                              init ist klar, die benötigt man in der einen oder anderen Art.
                              bgColorChange auch
                              createColorObj erzeugt Objekte die nur intern gebraucht werden. Wozu soll diese von außen zugreifbar sein?
                              getValue, da ist es sogar gefährlich diese nach außen zu legen, da diese den Wert für den aktuellen Schritt berechnet und jeder weitere Zugriff hier den Ablauf durcheinander bringen würde.
                              red, green, blue und bgElem sind eindeutig interne Daten und gehen keinen etwas an

                              Mich überzeugt das. Würde mich mal interessieren, wie Crockford das im Detail sieht. Ob Object-Notation mit teilweise öffentlichen (aber eigentlich privat sein sollenden) Variablen der Übersichtlichkeit halber einer Closure-Konstruktion vorzuziehen sind. Der einzige Grund kann ja die Übersichtlichkeit und somit Wartbarkeit sein. Vielleicht verstehe ich das Wort API ja auch falsch, aber die API, also die Schnittstelle, über die ich das Programm kunfiguriere und starte hat ja mit dem dahinter liegenden Code nix zu tun, oder?

                              Was nun wieder "eleganter" Code sein soll, erschließt sich mir immer noch nicht. Dazu wünschte ich mir ja ein Beispiel

                              1. hölzern, übersichtlich, praktikabel aber unelegant (und dennoch performant)
                              2. wie 1 nur eben "elegant"

                              Dachte, das könnte am Ende dieses Threads stehen. Vorher-Nachher-mäßig.

                              Gruß

                              jobo

                            2. Hallo,

                                
                              var BgChanger = {  
                                  createColorCycler : function (elem, rgbVals, rgbRanges) {  
                                      function createNextColorFunc(v, r) {  
                                          var value = v,  
                                              max = v,  
                                              range = r,  
                                              dir = 1;  
                                          return function () {  
                                              if (value <= max - range || value >= max) {  
                                                  dir *= -1;  
                                              }  
                                              value += dir;  
                                              return value;  
                                          };  
                                      }  
                                      var nextRed = createNextColorFunc(rgbVals[0], rgbRanges[0]),  
                                          nextGreen = createNextColorFunc(rgbVals[1], rgbRanges[1]),  
                                          nextBlue = createNextColorFunc(rgbVals[2], rgbRanges[2]);  
                                      return function () {  
                                          elem.style.backgroundColor = "RGB(" + nextRed() + "," + nextGreen() + "," + nextBlue() + ")";  
                                      };  
                                  },  
                                  start : function (elemId, rgbVals, rgbRanges, interval) {  
                                      var elem = document.getElementById(elemId);  
                                      window.setInterval(this.createColorCycler(elem, rgbVals, rgbRanges), interval);  
                                  }  
                              };  
                              window.onload = function () {  
                                  BgChanger.start("bgchange", [255, 168, 136], [55, 10, 16], 120);  
                              };  
                              
                              

                              BgChanger.start(parameterlist) ist der API-Aufruf?

                              auf createColorCycler kann jetzt immer noch zugegriffen werden, wobei das ja nicht so "schimm" ist, oder? Ansonsten wäre er in die start-Funktion zu verfrachten ...;

                              Gruß

                              jobo

                            3. Hallo,

                                
                              var BgChanger = {  
                                  start : function (elemId, rgbVals, rgbRanges, interval) {  
                                      var ColorHandler = {  
                                          red : {},  
                                          green : {},  
                                          blue : {},  
                                          style : {},  
                                          createColorObj : function (value, range) {  
                                              return {  
                                                  "value": value,  
                                                  "max" : value,  
                                                  "range" : range,  
                                                  "dir" : 1  
                                              };  
                                          },  
                                          nextVal : function (colorName) {  
                                              var c = this[colorName],  
                                                  val = c.value,  
                                                  max = c.max,  
                                                  range = c.range;  
                                              if (val <= max - range || val >= max) {  
                                                  c.dir *= -1;  
                                              }  
                                              c.value += c.dir;  
                                              return c.value;  
                                          },  
                                          change : function () {  
                                              this.style.backgroundColor = "RGB(" + this.nextVal("red") + "," + this.nextVal("green") + "," + this.nextVal("blue") + ")";  
                                          },  
                                          init : function (elemId, rgbVals, rgbRanges) {  
                                              this.style = document.getElementById(elemId).style;  
                                              this.red = this.createColorObj(rgbVals[0], rgbRanges[0]);  
                                              this.green = this.createColorObj(rgbVals[1], rgbRanges[1]);  
                                              this.blue = this.createColorObj(rgbVals[2], rgbRanges[2]);  
                                          }  
                                      };  
                                      ColorHandler.init(elemId, rgbVals, rgbRanges);  
                                      window.setInterval(function () {ColorHandler.change(); }, interval);  
                                  }  
                              };  
                              window.onload = function () {  
                                  BgChanger.start("bgchange", [255, 168, 136], [55, 10, 16], 120);  
                              };  
                              
                              

                              Gruß

                              jobo

                            4. Noch einmal die Links, die ich bereits gepostet habe:
                              Selbst dort finde ich "The main reason is that a programmer himself wants to get access to the encapsulated (please notice, I’m specifically not using term “hidden”) data. And if these data will be somehow incorrectly changed or there will be any error — the full responsibility for this is completely on the programmer, but not simply a “typing error” or “someone has casually changed some field”. But if such cases become frequent, we may nevertheless note a bad programming practice and style, since usually it’s the best to “talk” with objects only via public API." womit eigentlich alles gesagt ist.

                              Die Welt der Programmierung ist halt nicht schwarz/weiß. Weil das so ist, erlauben Ruby und Python den Zugriff, selbst wenn es schlechter Programmierstil ist und nach Möglichkeit vermieden werden sollte.

                              Ich behaupte keinesfalls dass man diese Möglichkeiten überhaupt oder gar häufig nutzen sollte. Ich wollte nur sagen, dass wir uns hier im Bereich von Konventionen, nicht von notwendig effektiver Kapselung bewegen. Kapselung als Pattern ist wichtig, aber es in Sondernfällen zu missachten ist den Entwickler von Ruby und Python so wichtig, dass sie es möglich gemacht haben. Übertragen auf JavaScript heißt das für mich, dass eine Pseudo-Kapselung z.B. mit Präfixen wie _ oftmals ausreicht.

                              Und meine Persönliche Erfahrung sagt mir, daß auf alles, was nicht gekapselt ist, auch aus irgendeinem Grund jemand zugreift.

                              Wenn ein Programmierer das tut, dann ist es halt sein Problem, wenn der Code irgendwann bricht (s.o.). Deswegen gibt es entsprechende Hindernisse.

                              Dann wird ein Balkon nach dem anderen an ein Objekt gebaut. Sind die Daten gekapselt, muss jemand der darauf Zugriff haben möchte mit dem Entwickler reden.

                              So funktioniert die Welt der Softwareentwicklung leider nicht immer, zumindest nicht die Open-Source-Welt hinsichtlich Ruby, Python und JavaScript. Manchmal bleibt einem nichts anderes übrig, als Code zu forken oder zu monkey-patchen. Dazu ist es praktisch, auf Interna zugreifen zu können. Das ist nicht schön und nicht ideal, aber Realität.

                              Sprachen wie Ruby und Python haben einfach keine effektive Kapselung.
                              Das mag sein, ist dann aber eine Schwachstelle der Sprache.

                              Das sehen die Designer dieser Sprachen ganz anders, sonst hätten sie diese Möglichkeit erst gar nicht eingeräumt, und die Entwickler dieser Sprachen sehen es auch anders und freuen sich, dass sie diese Möglichkeit für Ausnahmefälle und Übergangslösungen haben.

                              Gerade friend im C++ ist ja nicht dazu da, die Kapselung zu umgehen, sondern sie zu erhöhen, indem eine Methode nicht öffentlich gemacht werden muß, sondern einem speziellen Objekt Zugriff auf die Interna gestattet wird. Das ist auch nicht gut und auch immer anders lösbar, aber ein Kompromiss den man eingehen kann um größere Umstruckturierungen zu vermeiden, weil die Zeit fehlt.

                              Das klingt doch ziemlich vernünftig.

                              Mathias

                              1. Hallo Mathias,

                                wat is denn nu eleganter Code oder wenigsten befriedigend strukturierter Code?

                                https://forum.selfhtml.org/?t=209455&m=1425999
                                https://forum.selfhtml.org/?t=209455&m=1425989

                                Wollte wenigstens mal entweder eleganten oder wenigstens vernünftigen Code anhand dieses Beispiels haben. Es ist ja auch so überschaubar, dass sich das vermutlich bewerkstelligen lassen müsste.

                                Gruß

                                jobo

                    2. Hallo,

                      Man kann viel, einen wirklichen Grund dafür gibt es nicht. Diesen Code finde ich ziemlich unlesbar und unverständlich. Eine klassische OOP-Lösung, die mit tatsächlichen Objekten arbeitet, würde ich hier vorziehen.

                      [code lang=javascript]function createColorHandler(elem, prop, red, redRange, green, greenRange, blue, blueRange) {

                      createColorHandler ist ein ziemlich unpassender Name. Zurückgegeben wird ja eine Step-Funktion für eine Farb-Animation. Wieso nicht gleich die Animation als ganze wegkapseln?

                      Ist das jetzt ernst gemeint?

                      function createColorObj(v, r) {
                            var value = v;
                            var max = v;
                            var range = r;
                            var dir = 1;
                            return function() {
                              if (value <= max - range || value >= max) {
                                dir *= -1;
                              }
                              value += dir;
                              return value;
                            };
                          }

                      Hier wird kein Objekt erzeugt, sondern eine Closure. Kein Problem an sich, aber createColorObj ist kein passender Name, eher createNextColorFunc oder so.

                      Das habe ich schon mal geändert bei mir.

                      Vielleicht sollte jobo erst einmal versuchen, einfachen, klassischen OO-Code zu schreiben

                      naja, so hatte ich es ja versucht: https://forum.selfhtml.org/?t=209455&m=1425788, bzw. versucht, einen Kommentar für meinen Versuch zu erhaschen.

                      , verständliche APIs zu entwerfen und dann stärker funktional zu programmieren. Denn diesen Code finde ich alles andere als elegant.

                      Frustierend, denn ich dachte auf Anhieb, er wäre es. Ich dachte auch, gut strukturierter Code würde sich gerade dadurch auszeichen, dass eben der externe Zugriff und auf die Dinge möglich ist, auf die zugegriffen werden soll. So macht es Crockford in seinem Memoizer ja auch, wie hier verlinkt: https://forum.selfhtml.org/?t=209455&m=1425815

                      Gruß

                      jobo

                    3. Hallo,

                      Vielleicht sollte jobo erst einmal versuchen, einfachen, klassischen OO-Code zu schreiben, verständliche APIs zu entwerfen und dann stärker funktional zu programmieren. Denn diesen Code finde ich alles andere als elegant.

                      functional

                        
                      function cycleColors(elemStyle, rgbVals, rgbRanges) {  
                          function createNextColorFunc(v, r) {  
                              var value = v,  
                                  max = v,  
                                  range = r,  
                                  dir = 1;  
                              return function () {  
                                  if (value <= max - range || value >= max) {  
                                      dir *= -1;  
                                  }  
                                  value += dir;  
                                  return value;  
                              };  
                          }  
                          var nextRed = createNextColorFunc(rgbVals[0], rgbRanges[0]),  
                              nextGreen = createNextColorFunc(rgbVals[1], rgbRanges[1]),  
                              nextBlue = createNextColorFunc(rgbVals[2], rgbRanges[2]);  
                          return function () {  
                              elemStyle.backgroundColor = "RGB(" + nextRed() + "," + nextGreen() + "," + nextBlue() + ")";  
                          };  
                      }  
                        
                      window.onload = function () {  
                          window.setInterval(cycleColors(document.body.style, [255, 168, 136], [55, 10, 16]), 120);  
                      };  
                      
                      

                      vs.

                      OO

                        
                      var MyBgColor = {  
                          red : false,  
                          green : false,  
                          blue : false,  
                          style : false,  
                          createColorObj : function (value, range) {  
                              return {  
                                  "value": value,  
                                  "max" : value,  
                                  "range" : range,  
                                  "dir" : 1  
                              };  
                          },  
                          init : function (style, red, green, blue) {  
                              this.style = style;  
                              this.red = this.createColorObj(red.start, red.range);  
                              this.green = this.createColorObj(green.start, green.range);  
                              this.blue = this.createColorObj(blue.start, blue.range);  
                          },  
                          nextVal : function (colorName) {  
                              if (this[colorName].value <= this[colorName].max - this[colorName].range  
                                      || this[colorName].value >= this[colorName].max) {  
                                  this[colorName].dir *= -1;  
                              }  
                              this[colorName].value += this[colorName].dir;  
                              return this[colorName].value;  
                          },  
                          change : function () {  
                              this.style.backgroundColor = "RGB(" + this.nextVal("red") + "," + this.nextVal("green") + "," + this.nextVal("blue") + ")";  
                          }  
                      };  
                      window.onload = function () {  
                          MyBgColor.init(document.body.style, {start : 255, range : 55}, {start : 168, range : 10}, {start : 136, range : 16});  
                          window.setInterval(function () {MyBgColor.change(); }, 120);  
                      };  
                      
                      

                      Benamung ähnlich, Parameter variieren etwas.

                      35 vs. 25 Zeilen. Der funktionale Ansatz arbeitet mit privaten Variablen, was ja eigentlich doch sinnig erscheint (s. a. Crockford: http://javascript.crockford.com/private.html "This pattern of public, private, and privileged members is possible because JavaScript has closures. What this means is that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. This is an extremely powerful property of the language.")

                      Gruß

                      jobo

                      1. Hallo,

                        function cycleColors(elemStyle, rgbVals, rgbRanges) {

                        Würde ich createColorCycler oder ähnlich nennen, da eine Funktion zurückgegeben wird.

                        OO
                        var MyBgColor = {
                            red : false,
                            green : false,
                            blue : false,
                            style : false,
                            createColorObj : function (value, range) {
                                return {
                                    "value": value,
                                    "max" : value,
                                    "range" : range,
                                    "dir" : 1
                                };
                            },

                        Ich würde nicht behaupten, das das unbedingt eleganterer Code ist, er ist auf jeden Fall konventioneller und daher besser verständlich.

                        Die Idee von Crockford ist ja im Grunde, sich auf Konventionen zu einigen, die »sicher« sind im Sinne von Vermeidung von Fallstricken, wenn Programmierer unterschiedlicher Erfahrung zusammenkommen. Stark funktionale Programmierung mag der Sprache natürlich angemessener sein, erfordert aber Wissen, Erfahrung und Einarbeitungszeit. Mehrfach verschachtelte Funktionen, die Funktionen zurückgeben, sind einfach unübersichtlicher als ein flacher Objektliteral.

                        nextVal : function (colorName) {
                                if (this[colorName].value <= this[colorName].max - this[colorName].range
                                        || this[colorName].value >= this[colorName].max) {
                                    this[colorName].dir *= -1;
                                }
                                this[colorName].value += this[colorName].dir;
                                return this[colorName].value;

                        Hier wiederholt sich this[colorName] acht Mal. Besser wäre es, eine Shortcut-Variable anzulegen. Das macht es performanter und besser lesbar. (Auch max und value wird auch mehrfach zugegriffen.)

                        Der funktionale Ansatz arbeitet mit privaten Variablen, was ja eigentlich doch sinnig erscheint (s. a. Crockford: http://javascript.crockford.com/private.html "This pattern of public, private, and privileged members is possible because JavaScript has closures. What this means is that an inner function always has access to the vars and parameters of its outer function, even after the outer function has returned. This is an extremely powerful property of the language.")

                        Wie gesagt, Kapselung ist mehr ein Pattern denn notwendig ein konkretes Sprachfeature. Es besteht kein Zwang dazu, effektiv zu kapseln, und selbst bei vielen klassenbasierten Sprachen, die native private Eigenschaften haben, gibt es keine effektive (unüberwindbare) Kapselung.
                        http://dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory/#encapsulation

                        Objektorientierung und private Variablen widersprechen sich nicht. Closures kann man auch bei Konstruktoren einsetzen, und auch das Revealing Module Pattern trennt zwischen privaten und öffentlichen Daten. JavaScript gibt da einem viele Möglichkeiten und in Zukunft kommen noch weitere hinzu.

                        Mathias

                        1. Hallo,

                          OO
                          var MyBgColor = {
                              red : false,
                              green : false,
                              blue : false,
                              style : false,
                              createColorObj : function (value, range) {
                                  return {
                                      "value": value,
                                      "max" : value,
                                      "range" : range,
                                      "dir" : 1
                                  };
                              },

                          Ich würde nicht behaupten, das das unbedingt eleganterer Code ist, er ist auf jeden Fall konventioneller und daher besser verständlich.

                          Wenn Du mir dazu noch einen Hint geben könntest, was o.b. eleganter machen würde. red, green und blue müssen doch als Objekte irgendwo stehen? Abgesehen davon könnnte man wohl besser gleich red : {}, ... schreiben und statt style eben elem : {}, also alles schon als leeres Objekt initialisieren?

                          Zur Funktion createColorObj: Die zusammengehörenden Werte pro Farbe sind doch aber wohl Objekte und sollten doch wohl schon alleine aus DRY-Gründen in einer Funktion erzeugt werden, oder?

                          Würde später im Laufe des Tages Deine weiteren Anmerkungen mal einbauen.

                          API heißt ja wohl, dass ich im window.onload möglichst nur eine Funktion meines BgColorChanger-Objektes aufrufe, in der dann auch die setInterval-Funktion gestartet wird. Insofer ist der Interval-Parameter schon sinnig, weil er ja das Tempo bestimmt.

                          Sinngemäßg sollte also im window.onload nur stehen:

                          MyBgColorChanger:start(configObj) (oder init), wobei das Konfig-Objekt alle nötigen Startdaten enthält, inklusive des Intervalls, mit dem setInterval bestückt werden sollte, oder?

                          Bis später

                          Gruß

                          jobo

  3. Hallo,

    <script>  
    myObj = {  
        "testAttr" : "Bla"  
    }  
    function callTestAttr(attrName) {  
        alert(myObj.attrName); // undefined  
        alert(myObj[attrName]); // "Bla"  
    }  
    callTestAttr("testAttr");  
    </script>  
    
    

    Warum geht das eine und das andere nicht?

    Gruß

    jobo

    1. Hallo,

      <script>

      myObj = {
          "testAttr" : "Bla"
      }
      function callTestAttr(attrName) {
          alert(myObj.attrName); // undefined
          alert(myObj[attrName]); // "Bla"
      }
      callTestAttr("testAttr");
      </script>

      
      >   
      > Warum geht das eine und das andere nicht?  
      
      warum geht  
      var attrName = "testAttr";  
      alert(myObj.attrName);  
      nicht?  
      Bzw. warum ist myObj.attrName nicht definiert, wenn ich (nur) testAttr als Property an myObj definiere?
      
      1. Hallo,

        Hallo,

        <script>

        myObj = {
            "testAttr" : "Bla"
        }
        function callTestAttr(attrName) {
            alert(myObj.attrName); // undefined
            alert(myObj[attrName]); // "Bla"
        }
        callTestAttr("testAttr");
        </script>

        
        > >   
        > > Warum geht das eine und das andere nicht?  
        > warum geht  
        > var attrName = "testAttr";  
        > alert(myObj.attrName);  
        > nicht?  
        > Bzw. warum ist myObj.attrName nicht definiert, wenn ich (nur) testAttr als Property an myObj definiere?  
          
        Ja, genau, warum? ;-). In der (PHP-)"Hash-Schreibweise" object["attributName"] klappt es ja. Aber die ist ja wohl dafür da, Strings als Eigenschaften eines Objektes zu interpretieren. Aber object."attributName" geht eben nicht.  
          
        Gruß  
          
        jobo
        
        1. Hi,

          Aber object."attributName" geht eben nicht.

          Natürlich nicht, weil du auch hier wieder eine Doppeldeutigkeit hättest: Willst du die Objekteigenschaft attributName ansprechen - oder willst du das Ergebnis der toString-Methode von object mit dem Verkettungsoperator . mit dem Textliteral "attributName" verknüpfen ...?

          MfG ChrisB

          --
          RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
          1. Hallo,

            Hi,

            Aber object."attributName" geht eben nicht.

            Natürlich nicht, weil du auch hier wieder eine Doppeldeutigkeit hättest: Willst du die Objekteigenschaft attributName ansprechen - oder willst du das Ergebnis der toString-Methode von object mit dem Verkettungsoperator . mit dem Textliteral "attributName" verknüpfen ...?

            MfG ChrisB

            Das klingt mal logisch mit der Doppeldeutigkeit.

            Gruß

            jobo

        2. Aber object."attributName" geht eben nicht.

          Das ist wieder was anderes und das geht in keiner mir bekannten Sprache

          var test = "nicht test";
          var name = "test";
          var Obj = {
           test:  "attributName"
          };

          Obj.test    // Zugriff auf Obj.test
          Obj.name    // Obj hat keine Eigenschaft name
          Obj."test"  // syntaktisch falsch
          Obj["test"] // Zugriff auf Obj.test

    2. myObj = {
          "testAttr" : "Bla"
      }
      function callTestAttr(attrName) {
          alert(myObj.attrName); // undefined
          alert(myObj[attrName]); // "Bla"

      Meinst du das ernst?
      Du beschäftigst dich mit Crockford und stellst diese Grundlagenfrage?

      a.b greift immer auf eine Property namens »b« zu. »b« ist immer »b« ist immer »b«.

      Wenn du den Property-Namen hingegen aus einer Variable nehmen willst, er also nicht direkt aus dem Quellcode genommen werden soll, verwende die Bracket-Schreibweise. Diese erwartet einen String, bzw. zwischen den Brackets kann eine beliebige Expression stehen, also auch ein Variablenname. Diese Variable kann einen beliebigen String beinhalten.

      Mathias

      1. Hallo,

        myObj = {
            "testAttr" : "Bla"
        }
        function callTestAttr(attrName) {
            alert(myObj.attrName); // undefined
            alert(myObj[attrName]); // "Bla"

        Meinst du das ernst?
        Du beschäftigst dich mit Crockford und stellst diese Grundlagenfrage?

        Naja mein Interesse ist immer wieder auf Projektphasen beschränkt und durchaus auch eher hobbyhaft und theoretischer Art. Crockfords Ansichten beruhen ja im Grunde auf Überlegungen allgemeiner Art zu Fehlervermeidung und effizienter Strukturierung.

        a.b greift immer auf eine Property namens »b« zu. »b« ist immer »b« ist immer »b«.

        Ja, jetzt habe ich es (mal wieder) kapiert oder meine es ;-).

        Wenn du den Property-Namen hingegen aus einer Variable nehmen willst, er also nicht direkt aus dem Quellcode genommen werden soll, verwende die Bracket-Schreibweise. Diese erwartet einen String, bzw. zwischen den Brackets kann eine beliebige Expression stehen, also auch ein Variablenname. Diese Variable kann einen beliebigen String beinhalten.

        Genau, das war mir jetzt auch klar. In PHP gibt es eben $a = 4; $b = "a"; echo $$b; //4

        Wird aber nicht verwendet.

        bzw. eben $myString = "abc"; $myArray["abc"] = "def"; echo $myArray[$myString"; // "def";

        Das schon, wie ich dann eben auch bei meinem Script.

        Gruß

        jobo