Frank: Welche Vorteile bietet die Verwendung von Objekten von Objekten (sic!) in JS?

Nachdem ich am 20. Nov 99 eine Frage im Forum gestellt habe:

Objekte von Objekten (Definition:Wie?)

und von den Antworten ziemlich begeistert bin und sie deshalb jedem empfehlen möchte, stellt sich in diesem Zusammenhang auch noch die Sinnfrage. Bei mir wars fast Automatismus, meine Probleme in Objektform betrachten zu wollen (c++ Kenntnisse), aber was sagen die anderen?
Hat denn die Verwendung von Objekten von Objekten in JS überhaupt Vorteile gegenüber alternativen Lösungsmöglichkeiten? Wenn ja, immer? Wenn begrenzt, unter welchen Bedingungen? Wenn nein, warum nicht?

Deshalb meine Frage:
Welche Vorteile bietet die Verwendung von Objekten von Objekten (sic!)  in JS?

Frank

  1. Hallo Frank, hallo Roland,

    »»Bei mir wars fast Automatismus, meine Probleme in Objektform betrachten zu wollen (c++ Kenntnisse), aber was sagen die anderen?

    Ich bin dem Objektproblem weitgehend aus dem Weg gegangen. Nun Frank dein Posting hat mich veranlaßt, mich dem einmal zu stellen.
    Nun Roland hat zwar gedauert, aber ich hoffe, ich habe es kapiert. Wenn nicht zerreiß mich. :-)

    Hat denn die Verwendung von Objekten von Objekten in JS überhaupt Vorteile gegenüber alternativen Lösungsmöglichkeiten?

    Also so recht kann ich deine Fragen Frank auch noch nicht beantworten, aber ich stelle einfach mal ein Beispiel zur Diskussion. Ein Fuhrpark nur mit Autos ist ja recht langweilig. Zumindest ein Chef und eine Werkstatt mit Leitung gehören dazu. Also habe ich mal das Beispiel etwas erweitert und einen kleinen Fuhrpark kreiert.

    <html>
    <head>
    <title>Fuhrpark</title>
    </head>
    <body>
    <script language="JavaScript">
    <!--
    var Termin=new Array(),Werkstatt=new Array(),Auto=new Array();

    fuhrpark=new Fuhrpark("Meier","Helwig","Schmidt");

    function init()
    {
    Termin[0]=new termin("20.3.");
    Termin[1]=new termin("14.5")
    Termin[2]=new termin("15.3.")

    Auto[0]=new auto("Audi",2);
    Auto[1]=new auto("Opel",1);

    Werkstatt[0]=new werkstatt("Müller",2);
    Werkstatt[1]=new werkstatt("Helwig",0);
    }

    function auto(marke,zei)
    {
    this.leiter=fuhrpark.autoleiter;
    this.marke=marke;
    this.termin=zei;
    }

    function werkstatt(meister,zei)
    {
    this.leiter=fuhrpark.werkstattleiter;
    this.meister=meister;
    this.termin=zei;
    }

    function Fuhrpark(chef,autoleiter,werkstattleiter)
    {
    this.chef=chef;
    this.auto=Auto;
    this.autoleiter=autoleiter;
    this.werkstattleiter=werkstattleiter;
    this.werkstatt=Werkstatt;
    this.termin=Termin;
    }

    function termin(datum)
    {
    this.datum=datum;
    }

    function uebersicht()
    {
    for (i=0;i<Auto.length;i++)
    for (j=0;j<Werkstatt.length;j++)
    if (Auto[i].termin==Werkstatt[j].termin)
      {alert("Autotyp: "+Auto[i].marke
        +"\nWerkstatttermin am:"+ Termin[Auto[i].termin].datum
        +"\nbei Meister: "+Werkstatt[j].meister
        +"\nunter Werkstattleiter: "+Werkstatt[j].leiter);
       }
    }

    init();
    uebersicht();
    alert("Leiter Auto: "+Auto[0].leiter);

    function neuAuto(typ,ter)
    {
    Auto[Auto.length]=new auto(typ,ter);
    }

    function neuLeiter()
    {fuhrpark=new Fuhrpark("meier","Helwig","Wolf");init();
    uebersicht();}

    function autos()
    {for (i=0;i<fuhrpark.auto.length;i++) alert(fuhrpark.auto[i].marke)}

    //-->
    </script>
    <a href="javascript:neuAuto('Polo',2);">Neues Auto</a><br>
    <a href="javascript:uebersicht();">Werkstatttermin</a> <br>
    <a href="javascript:neuLeiter();">Neuer Werkstattleiter</a><br>
    <a href="javascript:autos();">Automarken des Fuhrparks</a>

    </body>
    </html>

    Ich stelle es jetzt einfach mal zur Diskussion.

    Viele Grüße

    Antje

  2. Hallo Frank!

    Objekte von Objekten (Definition:Wie?)

    Ich denke uebrigens, Du hast recht, dass zumindest in diesem Forum das Wissen um die Objekte noch nicht als abgesichert gelten kann. Woanders mag das anders sein. Aber: Wir arbeiten dran! ;-)

    und von den Antworten ziemlich begeistert bin und sie deshalb jedem empfehlen möchte, stellt sich in diesem Zusammenhang auch noch die Sinnfrage. Bei mir wars fast Automatismus, meine Probleme in Objektform betrachten zu wollen (c++ Kenntnisse), aber was sagen die anderen?

    Aah, ein Kenner also. :-) Ich habe auch immer viel klassenbasiert geschrieben, auch wenn's eigentlich gar nicht noetig war. Auf diese Weise waren meine Programme immer viel aufgeraeumter.

    Hat denn die Verwendung von Objekten von Objekten in JS überhaupt Vorteile gegenüber alternativen Lösungsmöglichkeiten? Wenn ja, immer? Wenn begrenzt, unter welchen Bedingungen? Wenn nein, warum nicht?

    Aeh... keine Ahnung. Ich glaube, Deine Fragen sind etwas zu allgemein gestellt. So grundlegend laesst sich das wohl kaum beantworten. Ausserdem hab ich da wohl auch nicht soviel Erfahrung damit.

    Sicher ist, mit der Power eines C++ kann JS beiweitem nicht Schritt halten. Dabei sind die Konzepte in C++ noch lange nicht der Gipfel der OOP.

    In JS sind Objekte nichts anderes als assoziative Arrays, die dynamisch erweitert werden koennen. Ich hatte ja schon erwaehnt, dass z.B. das
      window.frames.mainframe
    nichts anderes ist als
      window.frames['mainframe'].

    Man hat in JS allerdings auch das Prinzip der Vererbung nachgebildet, naeheres dazu findest Du auf http://developer.netscape.com/docs/manuals/js/client/jsguide/obj2.htm. Dort gibt es auch einen Vergleich zwischen JS und C++/Java in Bezug auf OO.

    Welche Vorteile bietet die Verwendung von Objekten von Objekten (sic!)  in JS?

    Tja, was groesseres hab ich JS noch nie gemacht. Mach einfach was Du machen willst, und wenn man es mit Objekten machen sollte, dann wirst Du es merken, dazu gibt's ja nun schliesslich die Intuition. ;-)

    Und was um Teufel bedeutet eigentlich sic! ? Ich hab das jetzt schon so oft gesehen...

    Antje: Ueber Deinen Quelltext muss ich erstmal ne Weile sinnieren. Willst Du auf irgendwas bestimmtes hinaus, auf was ich mich konzentrieren soll?

    Bis dann und wann

    P.S. Fur JS-Dokumentation ist http://developer.netscape.com/docs/manuals/javascript.html immer noch die Anlaufstelle Nummer 1. Einfach downloaden und lesen.

    1. Hallo Roland,

      Antje: Ueber Deinen Quelltext muss ich erstmal ne Weile sinnieren. Willst Du auf irgendwas bestimmtes hinaus, auf was ich mich konzentrieren soll?

      Ich hatte bislang mit objektorientierter Programmierung und Vererbung kaum zu tuen.
      Hier also mal meine Frage:
      Im Beispiel:
      Erweitert man die Objekte Auto und Werkstatt, wird dies vom Objekt Fuhrpark übernommen.
      Problempunkt:

      function neuLeiter()
      {fuhrpark=new Fuhrpark("meier","Helwig","Wolf");
      init(); /*Überschreibt die neue Leitereigenschaft*/
      uebersicht();}

      Ändert man das Objekt Fuhrpark werden die Änderungen  erst übernommen, nachdem nochmal die Funktion init() aufgerufen wurde. Warum?
      Ich fand es schon etwas seltsam, daß ohne init() auch für neue Autos der alte Leiter verwendet wurde und mit init() auch neuerstellte Autos mit der neuen Eigenschaft versehen werden, obwohl diese neuen Autos nicht neu initialisiert werden.

      Viele Grüße

      Antje

      1. Hallo Antje.

        Ändert man das Objekt Fuhrpark werden die Änderungen  erst übernommen, nachdem nochmal die Funktion init() aufgerufen wurde. Warum?
        Ich fand es schon etwas seltsam, daß ohne init() auch für neue Autos der alte Leiter verwendet wurde und mit init() auch neuerstellte Autos mit der neuen Eigenschaft versehen werden, obwohl diese neuen Autos nicht neu initialisiert werden.

        Das ist korrekt so. Ich weiß nicht, in wieweit Du bisher mit OO zu tun hattest. Es ist nur ein kleiner Denkfehler.
        Alleine durch die Ansammlung von Code ist das Objekt Fuhrpark noch nicht existent. Es sind nur seine Eigenschaften und Methoden definiert. Existent wird ein Fuhrpark erst, wenn eine Instanz angelegt wird, hier mit new Fuhrpark(...).
        Damit ist aber nur eine Instanz des Fuhrparks angelegt worden, nicht auch der Unterobjekte Auto und Werkstatt.
        Fuhrpark kann ohne Auto und Werkstatt nicht existieren. Mit 'var Termin=new Array(),Werkstatt=new Array(),Auto=new Array();' legst Du zwar außerhalb von Fuhrpark Instanzen von Auto, Termin und Werkstatt an, aber diese Instanzen werden nicht initialisiert.
        Würde diese Zeile fehlen, würde es bei new Fuhrpark() Fehlermeldungen hageln.

        Ich hoffe, das ist verständlich.

        Im übrigen hast Du Rekursionen in den Objekten. Auto kann nur angelegt werden, wenn ein Fuhrpark mit Autoleiter existiert. Der Fuhrpark wiederum benötigt jedoch mindestens ein Auto.
        JavaScript macht das zwar mit. Aber sauber ist das nicht.

        Hat denn die Verwendung von Objekten von Objekten in JS überhaupt Vorteile gegenüber alternativen Lösungsmöglichkeiten? Wenn ja, immer? Wenn begrenzt, unter welchen Bedingungen? Wenn nein, warum nicht?

        Frank, um Deine Frage zu beantworten:
        Antje hat mit dem Fuhrpark ein sehr schönes Beispiel für Objekte und Vererbung vorgestellt.
        Natürlich kann man das auch mit Spaghetticode definieren. Doch so ist der Code sauberer und übersichtlicher. Änderungen am Objekt Auto werden nur dort definiert, nicht noch an tausend anderen Stellen im Programm. Sinn der Objekte ist die Wiederverwendbarkeit. Spätestens ab einer gewissen Größe wird ein Programm ohne Objekte unhandlich. Ob  es sich lohnt für eine Formularabfrage oder zum Öffnen eines neuen Fensters eigene JavaScript Objekte zu definieren, sei dahingestellt. Für mich ist das mit Kanonen auf Spatzen geschossen.
        Spätestens, wenn mit mehrsimensionalen Arrays gearbeitet wird, sollte man sich überlegen, ob Objekte an dieser Stelle nicht geeigneter sind. Weiß man dann auch noch, daß der Code nach und nach ausgebaut werden soll, weitere Einträge oder gar weitere Dimensionen hinzukommen werden, sind Objekte eindeutig besser. Natürlich sind Objekte ihrerseits Arrays, aber eben eindimensionale. Das macht die Sache übersichtlicher und handlicher. Weiterhin können Objekte nicht nur Eigenschaften, sondern auch Methoden enthalten. So kann das Objekt Auto beispielsweise die Methode umbennen() besitzen und der Fuhrpark ebenso. Das sind zwei voneinender getrennte Funktionen.

        Bitte nachfragen, wenn das jetzt zu trocken war. OO zu erklären, ist nicht so ganz leicht.
        Viele Grüße
        Kess

      2. moin

        Ich will, dass es verschiedene Ebenen aufbaut, die ich dann mit mouse over über je ein Bild anzeigen will. In diese Ebenen muss ich aber klicken können bzw. mit der Maus drüberfahren, also kann ich sie nicht einfach mit onmouseout wieder ausblenden.

        Ich hab den Inhalt der Ebenen hier etwas gekürzt, wenn ihr dem Link folgt könnt ihr das ganze Problem sehen.

        Jups ! Als erstes sehe ich das der Code nen Unfall mit zehnfachem Überschlag ist. Die var ... = .... das ; nicht vergessen.

        • Warum packst du das alles in eine Tabelle ???? Die Bilder hintereinander zu setzen und bei Beginn einer neuen Zeile ein <br> tut es auch.

        • Dann hast du das mit deiner for() Schleife nicht zuende gedacht. Du schreibst da sich ständig wiederholenden Code. Das geht doch auch anders oder?
          Pack die Bilder in ein Array und bau dir ne writeIn() Schleife. Da die einzige var dort deine Quellangabe zum Bild ist.

        Was mich stört ist folgendes:

        Die Ebene "bild1" wird immer angezeigt, und die Ebenen "bild2" "bild3" "bild4" werden nicht ausgeblendet und ich kann immer nur eine Ebene mit einem höheren "bild-Wert" anzeigen.
        Aber das könnt ihr bei dem Link sehen......

        Wann sollen die denn ausgeblendet werden??? Du hast dazu doch gar keine Angabe gemacht. Das kleine Meinzelmänchen wird die nicht einfach so wegmachen??

        Aber ich denke mal wenn du eine neue Ebene öffnest! Dann must du doch nur die alte Ebene wieder "hidden" setzen.

        Hmmm was ist los ??? kein Bock mehr gehabt! Tja so einfach ist das halt nicht...

        cu

        1. Mmh, na Klasse! Irgendwie haut das mit Stefans 12000 Byte Beschraenkung nicht so ganz hin, es sei denn, Textpad luegt mich an. Naja, hier noch der Rest ab dem Body-Tag. Der Link http://www.geocities.com/SiliconValley/Lakes/1458/__foo/self_forum/fuhrpark.html sei aber dennoch empfohlen. (Nicht von diesem Yahoo-Werbemist ablenken lassen.)

          <BODY OnLoad="con = new CJSConsole(window.document.terminal.stdin, window.document.terminal.stdout);";>

          <!-- The following is part of the Calocybe JavaScript Console OnKeyPress="con.onStdinKeypress();" -->
          <FORM NAME="terminal">
          <BR>
          <B>stdin</B><BR>
          <TEXTAREA NAME="stdin" COLS="100" ROWS="5" WRAP="virtual"></TEXTAREA>
          <BR><BR>
          <B>stdout</B><BR>
          <TEXTAREA NAME="stdout" COLS="100" ROWS="20" WRAP="virtual"></TEXTAREA>
          </FORM>
          <!-- End Calocybe JavaScript Console -->

          </BODY>
          </HTML>

          So, nu aber

          1. Hi Calocybe,

            Mann, es ist schon beeindruckend, wie Du Dir die Nächte um die Ohren haust.

            Ich habe mir Dein Werk gleich mal ausgedruckt, um mich in die Windungen des Codes zu versteigen.

            Was das Beispiel mit dem Fuhrpark angeht, ist das von mir aus multi-okay, für die Verwendung in einem Artikel.

            Was treibst Du denn eigentlich tagsüber?

            Weiter so.

            Gruß
            Frank

            1. Hi Calocybe,

              ich finde, dass, wenn es mit dem Fuhrpark-Beispiel weitergehen soll, sollten wir uns eine vernünftige Objekthierarchie und -funktionalität überlegen.

              Klar scheint zu sein:
              Es gibt Autos, eine Werkstatt, einen Werkstattleiter, Werkstatttermine, einen Fuhrpark, einen Fuhrparkleiter und einen Chef. Da fehlt doch was!!! Der Sinn.

              Es wäre schön, wenn wir dieses Beispiel weiter entwickeln könnten. Vielleicht dadurch, dass
              wir nicht nur Objekte definieren, sondern ihnen auch Leben einhauchen.

              Skizze: Der Fuhrpark ist dazu bestimmt, Fahraufträge anzunehmen (Autos fahren lassen/ ich habe einen Stadtplan und auch gif-Autos). Die Werkstatt soll nicht nur den eigenen Fuhrpark in Schuss halten, sondern auch Fremdreparaturen durchführen (an Bremse, Kupplung, Motor), die eigenen Autos haben Inspektionstermine, die der Werkstattleiter beachten muss. Sonst kriegt der was aufs Dach. Der Fuhrparkleiter muss die Fahraufträge so zuteilen, dass sie möglichst alle an einem Tag abgearbeitet werden können und nicht für morgen übrigbleiben und die Eigenschaften der Autos müssen optimal berücksichtigt werden(Ladung, Tankstand). Sonst kriegt der was auf die Nuss und muss zur Strafe ...
              Das sieht schon fast nach einem Spiel aus, aber wo greift der Benutzer ein, was kann er gewinnen, was kann er falsch machen??? Wie setzt man das grafisch um? Etwa gif-Autos per Style-Sheets über einen Stadtplan fahren lassen? Macht das Spass??

              Ich habe den Eindruck es ufert aus. Naja, war nur sonne Idee.

              Gruss
              FRank

          2. Hallo Roland,

            mir fehlt es im Moment echt an Zeit mich damit auseinanderzusetzen. Ein Haufen Arbeiten schauen mich an und wollen korrigiert werden. :-)
            Übers Wochenende werde ich mich dann mal darin vertiefen.
            Aber trotzdem schon eine Kritik, der IE meckert die Zeilen

            31: captureEvents(Event.KEYPRESS);    
            und
            118  this.werkstaetten.push(werkstatt);

            an. Kannst sie ja in der Zwischenzeit ausbessern.

            Viele Grüße

            Antje

            1. Hi Leut's!

              mir fehlt es im Moment echt an Zeit mich damit auseinanderzusetzen. Ein Haufen Arbeiten schauen mich an und wollen korrigiert werden. :-)

              Kenne ich. Mir fehlt es eigentlich auch an Zeit, das hier zu schreiben. Ein Forumscript schaut mich an und will korrigiert werden... ;-)

              Aber trotzdem schon eine Kritik, der IE meckert die Zeilen

              »»

              31: captureEvents(Event.KEYPRESS);

              Ah ja, haette ich wohl dazu schreiben sollen, dass man es mit einem Browser und nicht mit dem Betriebssystem anschauen sollte (*g*), weil der IE hat ja ein anderes Eventmodell. Da kenn ich mich aber nicht aus (mit dem Netscapemodell eigentlich auch nicht, aber da kann ich es ja wenigstens ausprobieren). Kannst Du am Wochenende vielleicht gleich mit erledigen? Aber bitte erst am Montag posten, bin ueber's WE naemlich offline.

              und
              118  this.werkstaetten.push(werkstatt);

              Das kann der nicht?! Das ist aber JavaScript 1.2, sollte also eigentlich auch schon von den neueren 4er Versionen des IE gekonnt werden. Was hast Du denn fuer eine Version? Folgender Codeschnipsel koennte vielleicht Abhilfe leisten:

              if (!Array.push) Array.prototype.push = new Function("newelem", "this[this.length] = newelem;");

              Nagel mich nicht drauf fest, ich hab's nicht ausprobiert. Falls es funktioniert, ist das schon mal der erste Schritt in Richtung des naechsten Levels, naemlich Vererbung. *g*

              Frank: Tagsueber (also so ab um 12) mache ich langweiligere Sachen, dafuer krieg ich dann aber auch Geld. Ausser im Moment, da ist es ganz interessant, da baue ich einen URL-Minder, weil uns die fertige Loesung von Netmind ein paar Mark zu teuer war. Fuer privat ist http://mindit.netmind.com/ aber ganz praktisch und kostenlos.

              Und das mit dem Sinn... ist mir auch irgendwie aufgefallen. Ich wusste manchmal gar nicht so recht, *wie* ich etwas modellieren/implementieren sollte, weil mir nicht ganz klar war, was das Dasein so eines Fuhrparks eigentlich beinhaltet. Waere schon ganz sinnvoll, wenn man sowas vorher mal festlegt. *g*

              Noch ein paar Erlaeuterungen zu dem Objektmodell:
              Es gibt also ein CFuhrpark, mit den Eigenschaften Chef, Werkstattleiter, Autoleiter, einer Reihe von Werkstaetten und einer Reihe von Autos. Wenn ich das richtig verstanden habe, gehoeren Werkstaetten und Autos zum Fuhrpark dazu, sind also Eigenschaften des letzteren.

              Die Termine habe ich vorerst mal ebenfalls als Eigenschaften des Fuhrparks definiert, die von Werkstaetten und Autos "gekannt" werden. (Vom Standpunkt der objektorientierten Analyse ist das aber nicht gerade sauber.) Die Termine kennen der Einfachheit halber die Werkstatt und das Auto, fuer die sie gemacht wurden und stellen auf diese Weise eine Verbindung zwischen den beiden her (wiederum: nicht sauber!). Waehrend ein Auto nur einen Termin haben kann, koennen Werkstaetten mehrere haben und speichern die Referenzen auf diese Termine deshalb in einem Array.

              Wichtig ist der Unterschied zwischen "kennt jemanden" und einer Eigenschaft. Eine Eigenschaft ist eine unabhaenderlich zu einem Objekt gehoerige Sache. Jemanden zu kennen (auch als Assoziation bezeichnet) heisst, dass es sich bei dem anderen um etwas voellig eigenstaendiges (meist auch ein Objekt) handelt, was eine bestimmte Bedeutung fuer das "kennende" Objekt hat. So ist zum Beispiel die 'marke' eine Eigenschaft eines CAutos, der 'fuhrpark' wird jedoch gekannt, der ist nicht Teil des Autos. In der Implementierung stellt sich beides jedoch meist als Referenz (bzw. Pointer in C++) auf ein Objekt dar. Man kann daher aus einem Quelltext nicht zweifelsfrei das zugrundliegende Objektmodell erkennen. Das gilt zumindest fuer JS und C++, es soll jedoch auch richtige OO-Sprachen geben, die diesen Unterschied im Sourcecode repraesentieren (deswegen z.B. ist C++ eben keine echte OO-Sprache).

              Ein weiteres wichtiges Prinzip in der Objektorientierung wird von JS leider nicht unterstuetzt: die Datenkapselung. Man soll naemlich nicht einfach von aussen Zugriff auf fuhrpark.chef haben, da koennte ja jeder herkommen und das aendern, ohne dass es das Objekt selber merkt. Deshalb erklaert man diese Eigenschaft unter C++ als protected, was den Zugriff von aussen unterbindet. Fuer Abfragen und Neusetzen definiert man dann die Methoden CFuhrpark::GetChef() und CFuhrpark::SetNewChef(). Dies hat vor allem den Vorteil, dass das Objekt bei SetNewChef() selbst entscheiden kann, ob diese Aenderung noch weitere Auswirkungen hat und gegebenfalls Massnahmen ergreifen kann, um die eigenen Eigenschaften konsistent zu halten und andere betroffene Objekte von der Aenderung zu unterrichten.

              Ach ja, diese Schreibweise mit den zwei Doppelpunkten :: ist C++ und imho viel besser als die Javascript-Notation, wo die Objektmethoden letztlich ja doch nur normale, ueberall sichtbare Funktionen sind. Ich habe sie deshalb wenigstens mal in den Kommentaren erwaehnt.

              So, glaube das reicht erstmal. Also bye bye.