Thomas Schmidt: eval() oder nicht?

Hallo Forum,

hab mal wieder eine Frage. Ich möchte ein Objekt mit diversen Eigenschaften an eine Funktion übergeben, wobei einige Eigenschaften Namen von Variablen sind (varVisu), in welche die Funktion Werte schreiben soll.

Objekt sieht z.B. so aus:

  
  
  comm.varRdZyk = {  
  
       // Parameter für Lesen  
       indexGroup: indexGroups.M,  
       firstByte: 50,  
       readLength: 78,  
       runAfterPoll: anzeig.aktualAnzeig,  
       refreshTime: 10000,  
  
       //Zuordnungen  
        alloc: {  
            fenstKZ: {  
                varVisu: anzeig.fenst.kz,  
                varPlcType: 'BOOL',  
                varPlcAddr: 50  
            },  
            fenstSZ: {  
                varVisu: anzeig.fenst.sz,  
                varPlcType: 'BOOL',  
                varPlcAddr: 61  
            },  
            fenstWZOstLi: {  
                varVisu: anzeig.fenst.wz.ostLi,  
                varPlcType: 'BOOL',  
                varPlcAddr: 200  
            },  
  
            ......  
  
        }  
   }  
  

Mir fallen jetzt 2 Möglichkeiten ein. Entweder übergebe ich den Variablennamen als String und nutze eval() oder ich übergebe Objekte und lasse mir die Werte in eine Eigenschaft schreiben. Von eval() wird ja ständig abgeraten, auch aus Performance-Gründen. Die Liste hat ca. 70-80 Unterobjekte wie "fenstKZ" und soll ca. alle 200 ms abgearbeitet werden.
Was ist besser?

Schon mal vielen Dank,

Tom

  1. Hi,

    hab mal wieder eine Frage. Ich möchte ein Objekt mit diversen Eigenschaften an eine Funktion übergeben, wobei einige Eigenschaften Namen von Variablen sind (varVisu), in welche die Funktion Werte schreiben soll.

    Ich bin mir nicht sicher, ob ich dein Problem verstanden habe ...

    Mir fallen jetzt 2 Möglichkeiten ein. Entweder übergebe ich den Variablennamen als String und nutze eval() oder ich übergebe Objekte und lasse mir die Werte in eine Eigenschaft schreiben.

    Das man auf objekt.eigenschaft auch als object["eigenschaft"] zugreifen kann, ist bekannt?

    Von eval() wird ja ständig abgeraten, auch aus Performance-Gründen. Die Liste hat ca. 70-80 Unterobjekte wie "fenstKZ" und soll ca. alle 200 ms abgearbeitet werden.

    Was verstehst du unter "abarbeiten"? Das geht aus deinem Beispiel und deiner Fragestellung nicht hervor.

    MfG ChrisB

    --
    Light travels faster than sound - that's why most people appear bright until you hear them speak.
  2. Ich möchte ein Objekt mit diversen Eigenschaften an eine Funktion übergeben, wobei einige Eigenschaften Namen von Variablen sind (varVisu), in welche die Funktion Werte schreiben soll.

    Was genau machst du mit diesen Werten und warum nutzt du Variablennamen?

    Wenn du ein solches Objekt hast:

    {
    Visu: anzeig.fenst.kz,
    PlcType: 'BOOL',
    PlcAddr: 50
    }

    Kannst du doch prima auf die Eigenschaften zugreifen. Wieso musst du sie in Variablen umwandeln? Ws sind das für Variablen? Sollen das globale Variablen werden?

    Mir fallen jetzt 2 Möglichkeiten ein. Entweder übergebe ich den Variablennamen als String und nutze eval() oder ich übergebe Objekte und lasse mir die Werte in eine Eigenschaft schreiben.

    Du übergibst doch schon Objekte?
    Wenn du Objekteigenschaften befüllen kannst anstatt mit eval Variablen anzulegen (wieso solltest du?), dann tue dies.

    Was ist besser?

    Der Verzicht auf eval.

    Mathias

    1. »»  Ich möchte ein Objekt mit diversen Eigenschaften an eine Funktion übergeben, wobei einige Eigenschaften Namen von Variablen sind (varVisu), in welche die Funktion Werte schreiben soll.

      Was genau machst du mit diesen Werten und warum nutzt du Variablennamen?

      Wenn du ein solches Objekt hast:

      {
      Visu: anzeig.fenst.kz,
      PlcType: 'BOOL',
      PlcAddr: 50
      }

      Kannst du doch prima auf die Eigenschaften zugreifen. Wieso musst du sie in Variablen umwandeln? Ws sind das für Variablen? Sollen das globale Variablen werden?

      Das ganze ist eine Zuordnungsliste für einen Parser. Das Objekt stellt im Prinzip eine Verknüpfung dar, und zwar zwischen der Quelle (PlcAddr) und der Zielvariable (anzeig.fenst.kz) und der Angabe für die Konvertierungsmethode.
      Eine Funktion bekommt die Liste mit den Verknüpfungen und den Daten in Form eines Strings, schneidet Teile an Hand der Adresse aus, wandelt diese um und schreibt die Werte in die angegebene Zielvariable. Diese Zielvariablen werden vom Anwender vergeben.

      »» Mir fallen jetzt 2 Möglichkeiten ein. Entweder übergebe ich den Variablennamen als String und nutze eval() oder ich übergebe Objekte und lasse mir die Werte in eine Eigenschaft schreiben.

      Du übergibst doch schon Objekte?
      Wenn du Objekteigenschaften befüllen kannst anstatt mit eval Variablen anzulegen (wieso solltest du?), dann tue dies.

      »» Was ist besser?

      Der Verzicht auf eval.

      Mathias

      1. Hi,

        bitte zitiere vernünftig!

        Eine Funktion bekommt die Liste mit den Verknüpfungen und den Daten in Form eines Strings, schneidet Teile an Hand der Adresse aus, wandelt diese um und schreibt die Werte in die angegebene Zielvariable. Diese Zielvariablen werden vom Anwender vergeben.

        Also geht es eigentlich nur darum, Variablen zu befüllen, deren Namen als Strings übergeben werden?

        Nun, auch dafür gilt das, was ich bereits schrieb.
        Globale Variablen sind Eigenschaften des window-Objektes - mit diesen geht es also analog, wie mit den Eigenschaften anderer Objektinstanzen.

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
      2. Das ganze ist eine Zuordnungsliste für einen Parser. Das Objekt stellt im Prinzip eine Verknüpfung dar, und zwar zwischen der Quelle (PlcAddr) und der Zielvariable (anzeig.fenst.kz) und der Angabe für die Konvertierungsmethode.
        Eine Funktion bekommt die Liste mit den Verknüpfungen und den Daten in Form eines Strings, schneidet Teile an Hand der Adresse aus, wandelt diese um und schreibt die Werte in die angegebene Zielvariable. Diese Zielvariablen werden vom Anwender vergeben.

        Ehrlich gesagt verstehe ich dein Problem nicht ein Stück besser und weiß immer noch nicht, was ich dir raten soll.

        Ich weiß immer noch nicht, wieso du irgendwelche Variablen anlegen willst und warum du dazu eval verwenden willst. Aus Erfahrung kann ich nur sagen, dass man eval für solche Aufgaben nicht braucht. In JavaScript sind Objekte wie Hashes bzw. assoziative Arrays, also kannst du auf jede Objekteigenschaft mit einem String zugreifen - wie gesagt. Damit kannst du Daten unter einem Namen speichern und wieder abrufen:

        var objekt = { bla : "blub" };
        var eigenschaftsname = "bla";
        alert(objekt[eigenschaftsname]);

        Globale Variablen sind wie gesagt überhaupt nichts anderes, sie sind lediglich Eigenschaften des globalen Objektes window - aber ich würde dir davon abraten, globale Variablen zu verwenden.

        Mathias

        1. var objekt = { bla : "blub" };
          var eigenschaftsname = "bla";
          alert(objekt[eigenschaftsname]);

          Globale Variablen sind wie gesagt überhaupt nichts anderes, sie sind lediglich Eigenschaften des globalen Objektes window - aber ich würde dir davon abraten, globale Variablen zu verwenden.

          Das ist mir schon klar. Ich möchte aber nicht im "bla" was speichern, sondern im "blub". Daher kann ich als Wert für "bla" nur ein Objekt angeben. Wenn ich eine Variable oder Objekteigenschaft angebe, wird "bla" logischerweise deren Wert zugewiesen und keine Referenz.

          Ich verwende im richtigen Skript keine globalen Variablen. Ist alles in einen Namespace gepackt.

          Vielen Dank für eure Antworten. Ich werde eval() außen vor lassen und das über ein Objekt machen. Hat ja auch schon funktioniert.

          Tom

          1. Das ist mir schon klar. Ich möchte aber nicht im "bla" was speichern, sondern im "blub". Daher kann ich als Wert für "bla" nur ein Objekt angeben. Wenn ich eine Variable oder Objekteigenschaft angebe, wird "bla" logischerweise deren Wert zugewiesen und keine Referenz.

            Das ist unverständlich. Du kannst als Wert auch durchaus ein Objekt abspeichern, aber was ist das Problem?

            Struppi.

            1. Das ist unverständlich. Du kannst als Wert auch durchaus ein Objekt abspeichern, aber was ist das Problem?

              Wenn ich eine Objekt angebe, muss ich meine Daten einer Eigenschaft zuweisen. Der Anwender muss ein Objekt als Wert der Eigenschaft obj = { bla : blub } übergeben und bekommt er die Daten z.B. in blub.wert zurück. So weit ich das beurteilen kann, haben die Anwender des Skripts um einiges weniger Ahnung als ich und verwenden oft einfach globale Variablen. Schöner wäre es daher, ich könnte eine Variable Namens blub übergeben und die Daten darin speichern. Geht auch wenn, ich eval und den Namen als String verwende:

                
                
              var blub;  
                
              var obj = { bla : "blub" };  
                
              eval ( obj.bla + "=" + data + ";" );  
                
              
              

              Der Anwender soll halt nichts von den Requests usw. mitbekommen, sondern einfach schreiben können:

                
                
              var anwendervariable1, anwendervariable2, anwendervariable3;  
                
              serv = WebService.createService({  
                    url: 'http://....dll',  
                    spsId: '52.2.1.1',  
                    spsPort: '801'  
              })  
                
              var liste = {  
                
                    bereich: SPS-Merker,  
                    startAdr: 0,  
                    anzBytes: 170,  
                    timeout: 200,  
                
                      zuordnungen: {  
                
                          zuordn1: {  
                              zielvar: anwendervariable1,  
                              typ: 'BOOL',  
                              quelladr: 0  
                          },  
                          zuordn2: {  
                              zielvar: anwendervariable2,  
                              typ: 'STRING',  
                              quelladr: 1,  
                              laenge: 4  
                          },  
                          zuordn3: {  
                              zielvar: anwendervariable3,  
                              typ: 'BOOL',  
                              quelladr: 6  
                          },  
                
                         ...  
                
                          zuordnX: {  
                              zielvar: anwendervariableX,  
                              typ: 'INT',  
                              quelladr: 168  
                          }  
                
              }  
                
              serv.holeDaten(liste);  
                
              
              

              Die Funktion holeDaten() löst einen Request aus und bekommt die Daten vom Webservice in Form eines Strings zurück. Dann werden die Daten an Hand der Zuordnungsliste verarbeitet. Das Ganze ist für die Visualisierung von SPS-Daten gedacht.

              Funktioniert auch alles bestens, nur dass ich derzeit die Daten in anwendervariable1.data zurückschreibe und nicht in anwendervariable1. Ist mehr eine Sache der Schönheit. Wenn man von eval die Finger lassen sollte, dann lass ich das so.

              Tom

              1. var blub;

                var obj = { bla : "blub" };

                eval ( obj.bla + "=" + data + ";" );

                  
                Ich musste lange überlegen was du da willst. Ob das wirklich sinnvoll ist sowas vertracktest zu machen weiß ich nicht, aber das Gleiche geht z.b. so:  
                  
                `window[obj.bla] = data;`{:.language-javascript}  
                  
                Aber das wurde dir ja bereits gesagt, nur warum muss 'blub' Variabel sein? Wer definiert, das es blub gibt?  
                  
                Struppi.
                
                1. Ich musste lange überlegen was du da willst. Ob das wirklich sinnvoll ist sowas vertracktest zu machen weiß ich nicht, aber das Gleiche geht z.b. so:

                  window[obj.bla] = data;

                  Jetzt endlich hats gezündet und ich verstehe auch das Posting von Chris. Danke! Ich setze mich mit JS erst seit kurzem auseinander und da steh ich halt manchmal auf der Leitung.

                  Aber das wurde dir ja bereits gesagt, nur warum muss 'blub' Variabel sein? Wer definiert, das es blub gibt?

                  Struppi.

                  Das Ganze ist eine Art Framework für SPS-Visualsierungen über TwinCat-ADS-Webservices. Um so was wie AJAX-Requests und Base64-Dekodierung soll sich der Anwender nicht kümmern müssen. Und wie der Anwender seine Visu und sein SPS-Programm aufbaut und welche Variablen er verwenden will, kann ich nicht wissen. Daher möchte ich ein Maximum an Flexibilität bieten und es soll einfach zu handhaben sein. Ich kann dir das Skript zum Reinschauen gerne zuschicken, zum Posten ist es mittlerweile etwas zu lang geworden.

                  Vielen Dank an alle!

                  Tom

                  1. Ich glaub, das wird doch nichts, weil das mit einer Variable

                      
                      
                    var blub;  
                      
                    var obj = { bla : "blub" };  
                      
                    window[obj.bla] = data;  
                      
                    
                    

                    zwar funktioniert und data in blub speichert, aber mit Objekteigenschaften wie bei Verwendung eines Namespace gehts nicht:

                      
                      
                    var blub = {};  
                      
                    var obj = { bla : "blub.blubber" };  
                      
                    window[obj.bla] = data;  
                      
                    
                    

                    Tom

                    1. Hallo Thomas,

                      das ist jetzt ungetestet, aber probier es mal:

                      var blub = {};

                      var obj = { bla : "blub.blubber" };

                      var temp = obj.bla.split(".");  // zerlegt den String in Teilstrings

                      window[obj.bla] = data;

                      window[t[0]][t[1]] = data; // entspricht window[bla][blubber] = data
                                                 // entspricht window.bla.blubber = data

                        
                        
                      Gruß, Jürgen  
                      
                      
                      1. Das hab ich mir auch schon überlegt und es funktioniert auch. Ich muss dann halt noch eine Abfrage der Länge des Arrays basteln, weil ich ja nicht weiss, ob es nun "blub", "blub.blubber" oder noch verschachtelter wird.

                        So ähnlich (eine bessere Konstruktion ist mir nicht eingefallen):

                          
                          
                        var obj = { bla : "blub.blubber" };  
                          
                        var temp = obj.bla.split( "." );  // zerlegt den String in Teilstrings  
                          
                        switch( temp.length ) {  
                            case 1: window[temp[0]] = data;  
                                    break;  
                            case 2: window[temp[0]][temp[1]] = data;  
                                    break;  
                          
                            ....  
                          
                        }  
                          
                        
                        

                        Also entweder so oder ich lasse Objekt und Eigenschaft getrennt angeben:

                          
                          
                        zuordn1: {  
                                      zielObj: blub.blubber,  
                                      zielProp: "blablub",  
                                      typ: 'BOOL',  
                                      quelladr: 0  
                                  },  
                          
                        
                        

                        Dann kann ich auch mit zielObj[zielProp] arbeiten und, wenn zielObj nicht definiert wird, diesem das window-Objekt zuweisen.

                        Die erste Methode ist umständlicher, aber für den Anwender wahrscheilich einfacher. Mal sehen, was ich letztlich nehme ...

                        Danke,

                        Tom

                        1. Hi,

                          Das hab ich mir auch schon überlegt und es funktioniert auch. Ich muss dann halt noch eine Abfrage der Länge des Arrays basteln, weil ich ja nicht weiss, ob es nun "blub", "blub.blubber" oder noch verschachtelter wird.

                          So ähnlich (eine bessere Konstruktion ist mir nicht eingefallen):

                          Damit bist du natürlich auf die "Längen" von Objekt.Objekt.[...].Eigenschaft-Verkettungen limitiert, die die Cases in deinem Switch abdecken.

                          Ein anderer Ansatz wäre, die Referenz auf das letzte Objekt in der Reihe zu ermitteln, in dem man die Kette rekursiv durchläuft, und dann erst am Ende der daran hängenden Eigenschaft den Wert zuzuweisen.

                          MfG ChrisB

                          --
                          Light travels faster than sound - that's why most people appear bright until you hear them speak.
                    2. zwar funktioniert und data in blub speichert, aber mit Objekteigenschaften wie bei Verwendung eines Namespace gehts nicht:

                      var blub = {};

                      var obj = { bla : "blub.blubber" };

                      window[obj.bla] = data;

                        
                      Wenn du solche Dinge machst - also, es dir hochgradig kompliziert machst - dann wird vielleicht irgendwann kein Weg um eval herum führen, die Frage ist ob das wirklich sinnvoll ist.  
                        
                      Ich frag mich, was für Benutzer das sind, die einerseits Namespaces kennen, denen du anderseits aber nicht zutraust normale JS Objekte zu nutzen.  
                        
                      Struppi.
                      
  3. Hallo!

    Lasse die Finger von eval(). Benutze ein vorhandenes JSON-Objekt oder lade json.js nach. Auf diese Weise geht es schneller und Du hast nicht das Problem, dass Manipulationen am Objekt ein allzu großes Sicherheitsrisiko darstellen.

    Gruß, LX

    --
    RFC 1925, Satz 1: Es muss funktionieren.