Frank: Objekte, die Objekte enthalten (Definition: WIE?)

Hi,
ich möchte gern ein Objekt namens Fuhrpark erstellen, das mehrere Autos enthält, die ich dynamisch in einer Schleife erzeuge, etwa

for( var i=0; i< ...){
fuhrpark["auto" + i] = typ[i];
fuhrpark["auto" + i].gefahrene_kilometer = x;
fuhrpark["auto" + i].verbrauch = y;
fuhrpark["auto" + i].fahrer = z;
}

Hierbei sind  typ [i], x, y, z beliebige Variablenwerte. Wie muss ich das Objekt Fuhrpark definieren, wie das Objekt (?) Auto, damit das Ganze funktioniert.
Ich habe das in etwa so probiert wie beschrieben, ich erhalte aber immer undefined-Fehler.

Muchas gracias for some help

Frank

  1. Hallo!

    ich möchte gern ein Objekt namens Fuhrpark erstellen, das mehrere Autos enthält, die ich dynamisch in einer Schleife erzeuge, etwa

    Versuch's doch mal in etwa so:

    function Auto(t, km, v, f) {    // Constructor eines Auto-Objektes
        this.typ = t;
        this.gefahrene_kilometer = km;
        this.verbrauch = v;
        this.fahrer = f;
    }

    var fuhrpark = [];

    for (var i=0; i<... )
        fuhrpark["auto" + i] = new Auto(typ[i], x, y, z);

    Ich habe das in etwa so probiert wie beschrieben, ich erhalte aber immer undefined-Fehler.

    Immer dazu sagen, *an welcher Stelle* die Fehler auftreten, sonst muessen wir raten.

    Calocybe

  2. Hallo Frank,

    Dieses Problem klingt irgendwie nach einer Hausaufgabe :-).
    Ich werde mich deshalb um eine ausführlichere Erklärung bemühen. Lese auch <../../tebc.htm#a3>

    Hierbei sind  typ [i], x, y, z beliebige Variablenwerte. Wie muss ich das Objekt Fuhrpark definieren, wie das Objekt (?) Auto, damit das Ganze funktioniert.

    Was du benötigst ist zwei Objekte.
    Einmal das Objekt Fuhrpark und dann noch das Auto mit den jeweiligen Eigenschaften an.

    Fangen wir mit dem Fuhrpark an:

    An sich könntest du hier ein Array verwenden aber wenns halt neue Objekte sein sollen :-)

    Du definierst dir eine Funktion. Diese legt die Eigenschaft des Fuhrparkes -die Autonummer fest.

    function Fuhrpark(num)
    {this.num=num;}

    Anschließend machst du das Gleiche mit dem Auto selbst.

    function auto(marke,kilometer,verbrauch,fahrer)
    {
    this.marke=marke;
    this.kilometer=kilometer;
    this.verbrauch=verbrauch;
    this.fahrer=fahrer;
    }

    Wie du siehst sind hier die gesuchten Eigenschaften untergebracht.

    Jetzt kannst du daran gehen, die Objekte zu erzeugen:

    function newAuto()
    {for (i=0;i<4;i++)
      {new fuhrpark("auto"+i);
       fuhrpark["auto"+i]=new auto("Audi",3000,7,"Schulze");
       }
      alert(fuhrpark.auto2.marke)}

    Mit new Fuhrpark() erzeugst du das Objekt Fuhrpark.
    new ist ein reserviertes Wort zur Erzeugung eines neuen Objektes. Durch die Funktion Fuhrpark(num)wird diesem Objekt Eigenschaften zugewiesen. In diesem Fall Auto1. Deshalb auch die Verwendung von this. Dieses reservierte Wort spricht die aktuelle Instanz des aktuellen -hier neu erzeugtem Objektes an und weist ihm die neuen Eigenschaften zu.
    Anschließend werden diesem Objekt die Autoeigenschaften zu gewiesen, die man abfragen kann und das war es schon.

    Zum Testen hier mal ein Beispiel, bewußt modifiziert. Dieses erkläre ich nicht, aber du kannst ja mal versuchen mir zu erklären, was hier passiert.

    <html>
    <head>
    <title>Neue Objekte</title>
    </head>
    <body onLoad="newAuto()">
    <script language="JavaScript">
    <!--
    function auto(marke,kilometer,verbrauch,fahrer)
    {
    this.marke=marke;
    this.kilometer=kilometer;
    this.verbrauch=verbrauch;
    this.fahrer=fahrer;
    }
    M1=new Array("Audi","Opel","A4","A5");
    V1=new Array(2,3,4,5);

    function newAuto()
    {for (i=0;i<4;i++)
      {new auto();
       auto[i]=new auto(M1[i],3000,V1[i],"Schulze");
       }
      alert(auto[1].marke)}

    //-->
    </script>
    <p>Warum verzichte ich auf den Fuhrpark?</p>
       <p><a href="javascript:alert(auto[3].verbrauch);">Verbrauch</a>   </p>

    </body>
    </html>

    Viele Grüße

    Antje

    1. Hallo Antje!

      Och Antje, warum zwingst Du mich denn dazu...?!

      Also erstmal noch der obligatorische Hinweis: Man kann einen Quelltext auch lesbar aufschreiben, siehe weiter unten fuer Beispiele. ;-) Bei einem unlesbaren Quelltext nuetzt die beste Erklaerung nichts. Und nebenbei waeren Dir dann vielleicht weniger Fehler passiert. ;-(

      Du definierst dir eine Funktion. Diese legt die Eigenschaft des Fuhrparkes -die Autonummer fest.

      function Fuhrpark(num)
      {this.num=num;}

      Anschließend machst du das Gleiche mit dem Auto selbst.

      function auto(marke,kilometer,verbrauch,fahrer)
      {
      this.marke=marke;
      this.kilometer=kilometer;
      this.verbrauch=verbrauch;
      this.fahrer=fahrer;
      }

      Hier jetzt Deine reformatierte Funktion newAuto():

      function newAuto() {

      »»     for (i=0; i<4; i++) {
      »»         new fuhrpark("auto"+i);
      »»         fuhrpark["auto"+i]=new auto("Audi",3000,7,"Schulze");
      »»     }
      »»     alert(fuhrpark.auto2.marke)

      }

      Die Zeile   new fuhrpark("auto"+i);  ist erstens falsch (denn die Funktion Fuhrpark hast Du mit grossem F geschrieben) und zweitens sinnlos, da das eben erzeugte Objekt einfach weggeschmissen wird, weil Du den Rueckgabewert von new (naemlich das Objekt) an keine Variable zuweist. Dann willst Du auf fuhrpark["auto" + i] zugreifen, hast fuhrpark aber niemals deklariert (Fehlermeldung "fuhrpark is not defined"). Wahrscheinlich hast Du stattdessen folgendes gemeint:

      function newAuto() {
          for (i=0; i<4; i++) {
              fuhrpark = new Fuhrpark("auto"+i);
              fuhrpark["auto"+i]=new auto("Audi",3000,7,"Schulze");
          }
          alert(fuhrpark.auto2.marke)
      }

      Das ist aber immer noch ziemlich unsinnig, da Du in der Schleife viermal einen Fuhrpark anlegst, und dabei jeweils den vorher erzeugten ueberschreibst. Am Ende hast Du ein Objekt fuhrpark mit folgenden Eigenschaften:
          fuhrpark.num == "auto3"
          fuhrpark.auto3 == Objekt auto("Audi", 3000, 7, "Schulze")

      Die alert-Anweisung wird den Fehler "fuhrpark.auto2 has no properties" hervorrufen.

      Was Du wohl eigentlich gemeint hast, ist:

      var fuhrpark = new Fuhrpark(0);

      function newAuto() {
              for (i=0; i<4; i++) {
                  fuhrpark["auto"+i] = new auto("Audi",3000,7,"Schulze");
              }
              alert(fuhrpark.auto2.marke)
          }

      Wie Dir sicher auffaellt, ist der Parameter 'num' fuer Fuhrpark ueberfluessig. Ich habe ihn daher erstmal einfach mit 0 belegt. Mit diesem Code erhalst Du nun also ein Objekt fuhrpark mit folgenden Eigenschaften:

      fuhrpark.num == 0
          fuhrpark.auto0 == Objekt auto("Audi", 3000, 7, "Schulze")
          fuhrpark.auto1 == Objekt auto("Audi", 3000, 7, "Schulze")
          fuhrpark.auto2 == Objekt auto("Audi", 3000, 7, "Schulze")
          fuhrpark.auto3 == Objekt auto("Audi", 3000, 7, "Schulze")

      Nun nochmal Deine obigen Funktionen zusammen, damit Frank sie alle auf einen Blick hat:

      function Fuhrpark() {       // constructor fuer einen Fuhrpark
          }

      function auto(marke, kilometer, verbrauch, fahrer) {    // constructor fuer ein auto
              this.marke = marke;
              this.kilometer = kilometer;
              this.verbrauch = verbrauch;
              this.fahrer = fahrer;
          }

      var fuhrpark;

      function newAuto() {
              fuhrpark = new Fuhrpark();          // Anlegen von fuhrpark (Typ ist: Objekt Fuhrpark)
              for (i=0; i<4; i++) {
                  fuhrpark["auto"+i] = new auto("Audi", 3000, 7, "Schulze");
              }
              alert(fuhrpark.auto2.marke)
          }

      Mit  fuhrpark = new Fuhrpark()  erzeugst Du ein Fuhrpark-Objekt, das in der Variablen  fuhrpark  gespeichert wird.
      new ist ein reserviertes Wort zur Erzeugung eines neuen Objektes. Hinter new schreibt man den Namen einer Funktion, die das Objekt bei Bedarf mit bestimmten Werten initialisieren kann. Diese Funktion nennt man Constructor des Objektes und tut in obigem Beispiel gar nichts.

      Anschliessend werden in der for-Schleife 4 auto-Objekte erzeugt, die dann als Eigenschaften dem fuhrpark zugewiesen werden. Der Constructor des auto-Objektes nimmt 4 Parameter und initialisiert damit die Eigenschaften des Objektes (naemlich marke, kilometer, verbrauch, fahrer).

      Deshalb auch die Verwendung von this. Dieses reservierte Wort spricht die aktuelle Instanz des aktuellen -hier neu erzeugtem Objektes an und weist ihm die neuen Eigenschaften zu.

      Zuletzt wird in dem alert-Fenster der Wert von fuhrpark.auto2.marke ausgegeben (ist natuerlich "Audi"). Es ist dabei egal, ob man
          fuhrpark.auto2.marke        oder
          fuhrpark["auto2"].marke     oder
          fuhrpark.auto2["marke"]     oder
          fuhrpark["auto2"]["marke"]
      schreibt, alle vier Formen sind voellig gleichbedeutend.

      Zum Testen hier mal ein Beispiel, bewußt modifiziert. Dieses erkläre ich nicht, aber du kannst ja mal versuchen mir zu erklären, was hier passiert.

      (von mir ein bisschen ausgebessert)

      <html>
      <head>
          <title>Neue Objekte</title>
      </head>

      <body onLoad="newAuto()">

      <script language="JavaScript"><!--

      function auto(marke, kilometer, verbrauch, fahrer) {
              this.marke = marke;
              this.kilometer = kilometer;
              this.verbrauch = verbrauch;
              this.fahrer = fahrer;
          }

      M1=new Array("Audi","Opel","A4","A5");
          V1=new Array(2,3,4,5);

      autos = new Array();
          
          function newAuto() {
              for (i=0;i<4;i++) {
                  autos[i] = new auto(M1[i], 3000, V1[i], "Schulze");
              }
              alert(autos[1].marke)
          }

      //--></script>

      <p>Warum verzichte ich auf den Fuhrpark?</p>
      <p><a href="javascript:alert(auto[3].verbrauch);">Verbrauch</a>   </p>

      </body>
      </html>

      Sorry Antje, aber heute hast Du Dich nicht so sehr mit Ruhm bekleckert.
      Roland

      1. Hallo Roman,

        Och Antje, warum zwingst Du mich denn dazu...?!

        weil ich das erste mal damit überhaupt experimentiert habe und ich wußte, du kontrollierst schon :-)

        Also erstmal noch der obligatorische Hinweis: Man kann einen Quelltext auch lesbar aufschreiben, siehe weiter unten fuer Beispiele. ;-)

        werde ich das je lernen?

        Die Zeile   new fuhrpark("auto"+i);  ist erstens falsch (denn die Funktion Fuhrpark hast Du mit grossem F geschrieben)

        leider, ich hatte mehrfach am Posting etwas geändert und da hatte sich der Fehler eingeschlichen

        und zweitens sinnlos, da das eben erzeugte Objekt einfach weggeschmissen wird, weil Du den Rueckgabewert von new (naemlich das Objekt) an keine Variable zuweist.

        jetzt wird es recht interessant, schreibt man fuhrpark als Funktionsnamen klein, dann benötigt man keine Variablen die den Rückgabewert aufnehmen. Das hatte ich natürlich getestet. Durch meinen Fehler in der Groß- und Kleinschreibung kam es dann zur Fehlermeldung. Man sollte eben wohl doch kopieren :-)

        Das ist aber immer noch ziemlich unsinnig, da Du in der Schleife viermal einen Fuhrpark anlegst, und dabei jeweils den vorher erzeugten ueberschreibst.

        stimmt, allerdings wird tatsächlich nichts überschrieben
        und es existiert tatsächlich auto1 bis auto4.
        ich tippe darauf, es wird ein Feld über dieses Objekt angelegt.

        Im Grunde wird das gleiche wie bei den Array ablaufen.
        Neue Array gibt man ja auch mit new Array() an, und erst durch die Variablenzuweisung Feld=new Array() erhält man bequemen Zugriff darauf. new Array löscht ja auch nicht alle array.
        Übrigens ergibt alert(Array) ein interessantes Ergebnis.

        Wie Dir sicher auffaellt, ist der Parameter 'num' fuer Fuhrpark ueberfluessig.

        Das war auch der Fehlergrund, gerade das Überflüssigsein dieses Parameters :-)
        Korrigieren wir noch eine überflüssige Variable :-)

        Nun nochmal Deine obigen Funktionen zusammen, damit Frank sie alle auf einen Blick hat:

        function Fuhrpark() {       // constructor fuer einen Fuhrpark
            }

        function auto(marke, kilometer, verbrauch, fahrer) {    // constructor fuer ein auto
                this.marke = marke;
                this.kilometer = kilometer;
                this.verbrauch = verbrauch;
                this.fahrer = fahrer;
            }

        /*    var fuhrpark;  die braucht man nicht, da man ja ein neues Objekt erzeugt */

        function newAuto() {
                fuhrpark = new Fuhrpark();          // Anlegen von fuhrpark (Typ ist: Objekt Fuhrpark)
                for (i=0; i<4; i++) {
                    fuhrpark["auto"+i] = new auto("Audi", 3000, 7, "Schulze");
                }
                alert(fuhrpark.auto2.marke)
            }

        Ich korrigiere jetzt mal wieder einiges zurück :-)
        Du hast die Frage nämlich nicht beantwortet. Sie beantwortet auch gleichzeitig warum, meine Konstruktion klappte vorausgesetzt man schreibt den Funktionsnamen klein.

        <html>
        <head>
            <title>Neue Objekte</title>
        </head>

        <body onLoad="newAuto()">

        <script language="JavaScript"><!--

        function auto(marke, kilometer, verbrauch, fahrer) {
                this.marke = marke;
                this.kilometer = kilometer;
                this.verbrauch = verbrauch;
                this.fahrer = fahrer;
            }

        M1=new Array("Audi","Opel","A4","A5");
            V1=new Array(2,3,4,5);

        function newAuto() {
                new auto();
                for (i=0;i<4;i++) {
                    auto[i] = new auto(M1[i], 3000, V1[i], "Schulze");
                }
                alert(auto[1].marke)
            }

        //--></script>

        <p>Warum verzichte ich auf den Fuhrpark?</p>
        <p><a href="javascript:alert(auto[3].verbrauch);">Verbrauch3</a>
        <a href="javascript:alert(auto[2].verbrauch);">Verbrauch2</a>
        <a href="javascript:alert(auto[1].verbrauch);">Verbrauch1</a>
        <a href="javascript:alert(auto[0].verbrauch);">Verbrauch</a> </p>

        </body>
        </html>

        Sorry Antje, aber heute hast Du Dich nicht so sehr mit Ruhm bekleckert.

        Aber eine ganze Menge gelernt und das ist mir wichtiger :-)

        So und nun beantworte meine Frage auf der Beispielseite :-).

        Viele Grüße

        Antje

        PS: irgendwann mußten wir ja auf die Objekte zurückkommen.

        1. Hallo,

          Will für einen bestimmten Zweck ein ASP Formular über die Url ausfüllen u auch abschicken wie mache ich das, damit ich den submit button über die URL aktivieren kann???

          Das kannst Du mit einer einfachen if-Bedingung machen.
          Pruefe fuer einen Wert aus dem Querystring ob es ihn ueberhaupt gibt, wenn ja fuehre die gewuenschte submit-asp-Aktion aus (database Eintrag, email schicken, was auch immer)

          Also zB so:
          if len(trim(request.querystring("dingens")))>0 or len(trim(request("submitbutton")))>0 then
           ...mach irgendwas...
          end if

          Gruss, Mel

          1. Hallo Roland,

            diesmal richtig :-)

            ich habe es heute nicht gepackt mich damit zu beschäftigen. Aber ich bleibe dran.
            Ich hoffe, morgen ist er noch zu lesen und dann gibts eine ausführliche Antwort. Ausdiskutiert ist das nämlich noch nicht.

            Viele Grüße

            Antje

          2. Hallo Ihr,

            vielen Dank Antje und Roland für Eure Antworten, die für mich sehr lehrreich waren und geholfen haben. Ich empfehle die Lektüre allen, die sich mit eigenen Objekten in JS beschäftigen oder es noch wollen.
            Die Sache zeigt übrigens auch, dass die Problematik noch längst nicht in den gesicherten Bestand des Wissens und Handelns der JS-Gemeinde gehört. Das kann mit Euren Beiträgen nur besser werden. Also noch mal: Muchas Gracias!!!
            Ich werde nach dem Absenden noch eine neue Frage stellen im forum:
            Welche Vorteile bietet die Verwendung von Objekten von Objekten (sic!)  in JS?

            Chiaou
            Frank