JürgenB: Eval und Context

Hallo,

ich habe in einem String (Response eines http-Requests) Javascriptcode, in dem Variablen und Funktionen definiert werden. Wenn ich diesen Code im Context von window mit eval laufen lasse, kann ich später auf die Variablen und Funktionen zugreifen, da diese unter window angelegt werden. Lasse ich eval aber in einer Funktion laufen, werden die Funktionen und Variablen auch im Context dieser Funktion angelegt und ich habe von außerhalb keinen Zugriff mehr. Siehe folgendes Beispiel:

var code = ""  
    + "var x = 1;" + "\n"  
    + "window.y = 2;" + "\n"  
    + "var fkt1 = function(par) {" + "\n"  
    + "  alert(par);" + "\n"  
    + "}" + "\n"  
    + "window.fkt2 = function(par) {" + "\n"  
    + "  alert(par);" + "\n"  
    + "}" + "\n"  
    + "function fkt3(par) {" + "\n"  
    + "  alert(par);" + "\n"  
    + "}"; + "\n"  
  
   var uebersezte = function() { // Variablen und Funktionen im Context der Funktion  
    alert("with(window){\n"+code+"\n}");  
    eval ("with(window){\n"+code+"\n}");  
    if(typeof x != "undefined") alert(x); else alert("x nicht definiert");           // 1  
    if(typeof y != "undefined") alert(y); else alert("y nicht definiert");           // 2  
    if(typeof fkt1 != "undefined") fkt1("fkt1"); else alert("fkt1 nicht definiert"); // fkt1  
    if(typeof fkt2 != "undefined") fkt2("fkt2"); else alert("fkt2 nicht definiert"); // fkt2  
    if(typeof fkt3 != "undefined") fkt3("fkt3"); else alert("fkt3 nicht definiert"); // fkt3  
   }  
  
   window.onload = function() {  
     uebersezte();  
     if(typeof x != "undefined") alert(x); else alert("x nicht definiert");           // x nicht definiert  
     if(typeof y != "undefined") alert(y); else alert("y nicht definiert");           // 2  
     if(typeof fkt1 != "undefined") fkt1("fkt1"); else alert("fkt1 nicht definiert"); // fkt1 nicht definiert  
     if(typeof fkt2 != "undefined") fkt2("fkt2"); else alert("fkt2 nicht definiert"); // fkt2  
     if(typeof fkt3 != "undefined") fkt3("fkt3"); else alert("fkt3 nicht definiert"); // fkt3 nicht definiert  
   }  

Link zur Testseite

Ich habe hier schon mit "with" experimentiert, hat aber keinen Erfolg gebracht.

Gibt es eine Möglichkeit, eval im Kontext von window laufen zu lassen? Die im Beispiel bei y und fkt2 angewandte Methode, mit window.y und window.fkt2 zu arbeiten, ist nur eine Notlösung, da ich dann die Script umschreiben müsste.

Gruß, Jürgen

  1. Hallo, Jürgen!

    Warum fügst Du nicht einfach einen entsprechenden script-Tag ein? Dann sparst Du Dir das Problem mit eval und zudem die Same-Domain-Policy.

    Gruß, LX

    --
    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: Unusual
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo LX,

      Warum fügst Du nicht einfach einen entsprechenden script-Tag ein? Dann sparst Du Dir das Problem mit eval und zudem die Same-Domain-Policy.

      das habe ich auch schon ausprobiert. Das Problem mit dem falschen Context wird dadurch auch gelöst, leider läuft die Abarbeitung des so eingebundenen Scriptes asynchron ab, so das die Objekte erst nach einer kurzen Wartezeit verfügbar sind. Das Testbeispiel würde so sogar funktionieren, aber wenn das eingebundene Script (ich benutze einen synchronen Request) länger wird, bei mir waren es etwa 10 kB, ist die eingebundene Funktion direkt nach dem Laden und evaluieren "undefined" und erst nach einem alert konnte ich sie aufrufen.

      Vielleicht noch etwas mehr Hintergrund: Ich möchte Scripte erst bei Bedarf laden. Das mache ich folgendermaßen:

        
      if (typeof(Methode)!="function") lade_und_evaluiere("script_mit_Methode.js);  
      Methode();  
      
      

      Dazu muss das Script bei Beendigung von lade... sofort verfügbar sein. Und da es mein Wunsch ist, die Scripte sowohl mit "<script src=..." als auch dynamisch einzubinden, kommt ein asynchroner Request mit anschließendem Erstellen eines script-Tags und Zuweisung über die text-Eigenschaft nicht in Frage. Denn hierbei würde ich eine Callback-Funktion benötigen und müsste die Programmlogik ändern.

      Gruß, Jürgen

      1. Du könntest genausogut einen Skript-Tag mit innerText bzw. innerHTML erstellen (je nach Browser). An Deiner Stelle würde ich mir die Lösungen bei den gängigen JS-Toolkits ansehen und den Versuch aufgeben, das Rad neu zu erfinden.

        Gruß, LX

        --
        RFC 1925, Satz 6: Es ist einfacher, ein Problem zu verschieben (...), als es zu lösen.
        1. Hallo LX,

          Du könntest genausogut einen Skript-Tag mit innerText bzw. innerHTML erstellen (je nach Browser).

          das habe ich alles schon ohne Erfolg getestet.

          An Deiner Stelle würde ich mir die Lösungen bei den gängigen JS-Toolkits ansehen und den Versuch aufgeben, das Rad neu zu erfinden.

          Ich wollte das Rad auch nicht neu erfinden, daher war der Link von Mathias genau richtig. Inzwischen habe ich die Lösung auch im Opera und im Safari unter WinXP erfolgreich getestet.

          Gruß, Jürgen

  2. Gibt es eine Möglichkeit, eval im Kontext von window laufen zu lassen?

    Hast du mal das ausprobiert:

    http://josephsmarr.com/2007/01/31/fixing-eval-to-use-global-scope-in-ie

    Mathias

    1. Hallo molily,

      Hast du mal das ausprobiert:

      so eben getestet. Es funktioniert. Danke für den Tipp.

      Da ich die Testseite in einigen Tagen löschen werde, hier noch mal meine momentane Lösung, die im FF 3 und im IE 7 funktioniert:

        
          if (window.execScript) window.execScript(code);  
          else window.eval(code);  
      
      

      Die Fehlerbehandlung fehlt noch.

      Gruß, Jürgen