Andreas: window[] statt eval in Namensräumen?

Hallo!

Bisher habe ich zum Aufrufen von Funktionen mit dynamischen Funktionsnamen das hier gemacht:

function Funktionsname() {
  // Mach was
}

window["Funktionsname"] ("Gimmicks");

Jetzt liegt das Ganze aber in einem Namensraum:

var meinSkript = (function() {
   window["Funktionsname"] ("DiesUndDas");
}) ();

Und da funktioniert das nicht mehr. Ich verstehe auch ungefähr warum. window[] ist ja nicht mehr das übergeordnete Objekt der Funktion. Aber wie ist es nun richtig?

window[this]["Funktionsname"] habe ich schon probiert.

Gruß,
Andreas.

  1. Hi,

    Und da funktioniert das nicht mehr.

    dann machst Du irgend etwas falsch.

    Ich verstehe auch ungefähr warum. window[] ist ja nicht mehr das übergeordnete Objekt der Funktion.

    Nein, das window-Objekt ist immer noch das selbe.

    Aber wie ist es nun richtig?

    window["Funktionsname"], window.Funktionsname, Funktionsname.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo Cheatah,

      ich habe vergessen zu erwähnen, dass die aufzurufende Funktion innerhalb des Namensraums liegt. Also so:

        
      var meinSkript = (function() {  
         function Funktionsname() {  
           // Mach was  
         }  
        
         window["Funktionsname"] ("DiesUndDas");  
      }) ();  
      
      

      Und das funktioniert eben nicht.

      1. Hi,

        ich habe vergessen zu erwähnen, dass die aufzurufende Funktion innerhalb des Namensraums liegt. Also so:

        ah, ja. Warum rufst Du sie nicht einfach auf die Weise auf, auf die Funktionen ganz traditionell aufgerufen werden?

        Cheatah

        --
        X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
        X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Na weil der Funktionsname dynamisch ist. Das Skript ist im Ganzen schon etwas komplexer.

          1. Ah, hab’s gefunden! Für die Nachwelt:

              
            var meinSkript = (function() {  
              this.Funktionsname = function() {  
                 // Mach was  
               }  
              
               this["Funktionsname"] ("DiesUndDas");  
            }) ();  
            
            
            1. Hallo,

              var meinSkript = (function() {
                this.Funktionsname = function() {
                   // Mach was
                 }

              this["Funktionsname"] ("DiesUndDas");
              }) ();

                
              Jetzt wirfst du vermutlich einiges durcheinander. Du musst dir bloß den Unterschied zwischen globalen und lokalen Variablen in Erinnerung rufen:  
                
              bla = ...; erzeugt in einer Funktion eine globale Variable, d.h. ein Unterobjekt von window,  
              var bla = ...; eine lokale Variable.  
                
              Das gilt immer, egal, was auf der rechten Seite der Zuweisung steht. Da kannst du natürlich auch eine Function Expression, also function (...) {...}  notieren. Du könntest deshalb genauso  
              bla = function () {};  
              schreiben.  
                
              this ist nichts anders als window, solange die Funktion nicht in einem bestimmten anderen Kontext ausgeführt wird. Wenn du immer window willst, solltest du auch window schreiben.  
                
              window.bla = function () {}; erzeugt immer eine globale Funktion und du kannst eben über window["bla"] darauf zugreifen.  
                
              Mathias
              
              -- 
              [SELFHTML aktuell Weblog](http://aktuell.de.selfhtml.org/weblog/)
              
              1. Hallo!

                Jetzt bin ich völlig durcheinander … also es ist so, wie Struppi schon vermutet hat. Ich verwende ein Objekt. Mit this bin ich tatsächlich nicht sehr weit gekommen, da ich mit Event-Handlern arbeite und es dadurch zu Fehlern kam. Jetzt verzichten ich auf this und schreibe stattdessen meinSkript.Methode = function() {}. So funktioniert alles. Ist das trotzdem noch nicht richtig?

                Versuche mich seit Wochen in das Thema Namensräume einzuarbeiten, hauptsächlich mit Deinem Artikel, Mathias ("Organisation von JavaScripten"). Fällt mir trotzdem extrem schwer so umzudenken.

                1. Jetzt bin ich völlig durcheinander … also es ist so, wie Struppi schon vermutet hat. Ich verwende ein Objekt. Mit this bin ich tatsächlich nicht sehr weit gekommen, da ich mit Event-Handlern arbeite und es dadurch zu Fehlern kam. Jetzt verzichten ich auf this und schreibe stattdessen meinSkript.Methode = function() {}. So funktioniert alles. Ist das trotzdem noch nicht richtig?

                  Vermutlich nicht (du bist sehr zurückhaltend mit Codebeispielen)

                  Der Punkt bei eventhandler ist, dass im Eventaufruf, this dem Objekt, auf dem der event stattfindet, entpricht. Zu Verdeutlichung:

                  function deinObjekt(id) {  
                  var element = document.getElementById(id);  
                  element.onclick= function(e) {  
                  // hier ist this == element  
                  };  
                  }
                  

                  um das zu umgehen, verwendet man ein lokale Variabel, die dann im eventaufruf ihre Gültigkeit behält.

                  function deinObjekt(id) {  
                  var self = this;  
                  var element = document.getElementById(id);  
                  element.onclick= function(e) {  
                  // hier kannst du dann über self auf die Funktionen des Objektes zugreifen  
                  };  
                  }
                  

                  Struppi.

                  1. Danke für eure Erklärungen. Ich denke, jetzt hab ich’s. Funktioniert auch alles super.

                    Grüße,
                    Andreas.

                2. Hallo!

                  Jetzt bin ich völlig durcheinander … also es ist so, wie Struppi schon vermutet hat.

                  Bringen wirs nochmal auf den Punkt.

                  Wie Molily dir schon zu erklären versucht hat, werden Geltungsbereiche (Scopes) in Javascript auch in Objekten realisiert. Der "Global Scope" ist dabei identisch mit dem Host Objekt (also hier window), das nutzt du auch aus.

                  Der "Local Scope" hingegen ist nicht namentlich adressierbar, deswegen spricht man auch schließlich von PRIVATEN Variablen und deklariert sie mit "var". Also verhindert JS absichtlich, das dieses Objekt benennbar ist und du kannst kein name[string] darauf anwenden,

                  Deswegen weise deine "Dynamischen Funktionsnamen" auch einem Objekt zu, das man benennen kann (Molily nannte dir Möglichkeiten) oder benutze doch eval.

                  Die "Spezialvariable" this ist hier komplett fehl am Platz, this ist bei Aufrufen der Verweis auf das Objekt dessen Methode du aufrufst, sprich was vor dem letzten Punkt eines Aufrufs steht. Folglich ist bei einer Konstruktion mit "new"  "this" das zu bestückende "neue" Objekt.

                  Rufst du ohne Punkt eine Funktion global auf, rufst du implizit über "window" eine Methode auf, also gilt dann auch this===window.

                    
                  function echo(txt){document.writeln(txt+"<br>")}  
                    
                  a=new Object;  
                  a.b=new Object;  
                    
                  function test() {  
                    b1=(this === window);  
                    b2=(this === a);  
                    b3=(this === a.b);  
                    echo(b1+" "+b2+" "+b3);  
                  };  
                    
                    
                  a.test=test;  
                  a.b.test=test;  
                    
                  test();     //true false false  
                  a.test();   //false true false  
                  a.b.test(); //false false true  
                  
                  

                  Alles klar? :)

                  so long
                    LanX

            2. Ah, hab’s gefunden! Für die Nachwelt:

              var meinSkript = (function() {
                this.Funktionsname = function() {
                   // Mach was
                 }

              this["Funktionsname"] ("DiesUndDas");
              }) ();

                
              this ist in diesem Fall das gleiche wie window. Ich nehme an, dass du irgendwo ein Objekt hast, das würde diese Schreiweise erklären. Aber so allgemein wie du es schreibst taugt das nicht für die Nachwelt.  
                
              Struppi.
              
      2. Hallo,

        Verschachtelte Funktionen sind lokale Variablen. Auf das Objekt, an dem die lokalen Variablen hängen, kannst du nicht direkt zugreifen. Also ist die Ansprechweise objekt["unterobjekt"] nicht direkt möglich. Du kannst das Funktionsobjekt aber natürlich an ein anderes lokales Objekt hängen und dann über diese Schreibweise darauf zugreifen.

        var meinSkript = (function() {
           function Funktionsname() {
             // Mach was
           }

        window["Funktionsname"] ("DiesUndDas");
        }) ();

          
        Warum schreibst du var meinSkript davor? Hat die anonyme Funktion denn einen Rückabewert?  
          
        ~~~javascript
        function bla () {  
           var lokalesObj = new Object;  
           var fname = "foo";  
           lokalesObj[fname] = function (...) {...};  
           alert(lokalesObj[fname]);  
        }
        

        Alternativ kannst du die Funktionsobjekt am äußeren Funktionsobjekt selbst speichern. Darauf greifst du mit arguments.callee zu.

        var thisF = arguments.callee;
        thisF[fname] = ... wie oben.

        Das macht Sinn, wenn du sie außerhalb noch einmal brauchst.

        Mathias

        1. Hi Matthias,

          Verschachtelte Funktionen sind lokale Variablen. Auf das Objekt, an dem die lokalen Variablen hängen, kannst du nicht direkt zugreifen.

          ..

          Alternativ kannst du die Funktionsobjekt am äußeren Funktionsobjekt selbst speichern. Darauf greifst du mit arguments.callee zu.

          das der globale Scope am Window Object hängt ist klar, aber ist der lokale Scope wirklich als (abgeschottetes) inneres Funktionsobjekt organisiert / implementiert?

          konnte dazu nix finde.

          Grüße
           Kurt

          1. Hi

            konnte dazu nix finde.

            tatsächlich, ECMA262-3 Kap. 10.1.3 spricht von einem "variable object".

            interessant :)

            Grüße
              Kurt