MichaelR: +OBJEKTE + Definieren von Methoden

Hallo,

bin gerade dabei mein Theoriewissen über die Objekte, welche ich selber einer HTML Seite hinzufügen kann mittels myObj = new ObjectDef(); etc..

Dabei lese ich das Tutorial von Dan Steinman (www.dansteinman.com) zu diesem Thema - die Ausführungen zu den Browsern sind zwar alle für die 4er Generation aber die Theorie ist ja weitgehend noch aktuell.

Jetzt meine Frage:

Steinman schreibt da, wenn ich einem Objekt Methoden hinzufügen will, so solle man das am besten mit Hilfe des "prototype" machen:

Bsp:

function NeueFunktion(){
...
}

MyObject.prototype.NeueFkt = NeueFunktion;

Er schreibt weiterhin, die Variante, dass ich die Funktion gleich bei der Erzeugung des Objekts anhänge

function MyObject(){

// properties:
this.h = '';
...

// methods:
this.NeueFkt = NeueFunktion;
}

seie nicht zu empfehlen.
Grund (wenn ich das richtig verstanden hab'): alle Objekte würden jetzt "Prototyping" verwenden ?!

Frage: Ist das immer noch so, dass man besser prototype verwenden sollte, oder doch nicht ?

Grüße
Michael

  1. Hallo MichaelR,

    bin gerade dabei mein Theoriewissen über die
    Objekte, welche ich selber einer HTML Seite
    hinzufügen kann mittels myObj = new
    ObjectDef(); etc..

    Du fuegst einer HTML-Seite keine Objekte zu, du
    erzeugst JS-Objekte.

    Steinman schreibt da, wenn ich einem Objekt
    Methoden hinzufügen will, so solle man das am
    besten mit Hilfe des "prototype" machen:

    Wenn du einem per new erzeugtem eine neue Methode
    hinzufuegen willst, solltest du das ueber den
    Prototypen machen, ja. Wenn du generell einem
    Objekt eine Methode geben willst, machst du das
    am besten im Konstruktor per

    this.method = funktion;

    Grund (wenn ich das richtig verstanden hab'):
    alle Objekte würden jetzt "Prototyping"
    verwenden ?!

    Ich glaube, du hast da was falsch verstanden. Das
    prototype-Objekt fuegt das Objekt (ja, eine
    Funktion *ist* ein Objekt) *jeder* vorhandenen
    Instanz des Objekts zu. Willst du also
    *nachtraeglich* allen Objekten eine Methode
    verpassen (oder eine vorhandene ueberschreiben),
    dann ist prototype dein Freund. Willst du nur
    *einer* Instanz nachtraeglich eine Methode
    verpassen, solltest du das ueber

    obj.method = funktion;

    machen. Dabei kann obj durchaus auch this sein.
    Willst du einem Objekt *generell* eine Methode
    verpassen, ist die Zuweisung im Konstruktor
    durchaus eine sinnvolle (und performante) Loesung.

    Gruesse,
     CK

    1. Hi CK,

      bin gerade dabei mein Theoriewissen über die
      Objekte, welche ich selber einer HTML Seite
      hinzufügen kann mittels myObj = new
      ObjectDef(); etc..

      Du fuegst einer HTML-Seite keine Objekte zu, du
      erzeugst JS-Objekte.

      Meinte ich ja :)

      Steinman schreibt da, wenn ich einem Objekt
      Methoden hinzufügen will, so solle man das am
      besten mit Hilfe des "prototype" machen:

      Wenn du einem per new erzeugtem eine neue Methode
      hinzufuegen willst, solltest du das ueber den
      Prototypen machen, ja. Wenn du generell einem
      Objekt eine Methode geben willst, machst du das
      am besten im Konstruktor per

      this.method = funktion;

      Grund (wenn ich das richtig verstanden hab'):
      alle Objekte würden jetzt "Prototyping"
      verwenden ?!

      Ich glaube, du hast da was falsch verstanden. Das
      prototype-Objekt fuegt das Objekt (ja, eine
      Funktion *ist* ein Objekt) *jeder* vorhandenen
      Instanz des Objekts zu. Willst du also
      *nachtraeglich* allen Objekten eine Methode
      verpassen (oder eine vorhandene ueberschreiben),
      dann ist prototype dein Freund. Willst du nur
      *einer* Instanz nachtraeglich eine Methode
      verpassen, solltest du das ueber

      obj.method = funktion;

      machen. Dabei kann obj durchaus auch this sein.
      Willst du einem Objekt *generell* eine Methode
      verpassen, ist die Zuweisung im Konstruktor
      durchaus eine sinnvolle (und performante) Loesung.

      Ok, das klärt mein Problem sehr gut, danke.
      Die Methoden sind alle bereits vor dem Erzeugen der Objekte vorhanden und werden - wie Du schreibst - mit

      Obj.method = funktion;

      angehängt.
      Somit hat jedes neues Objekt beim Erzeugen bereits alle Funktionen dabei.

      Ok, vielen Dank
      Grüße
      Michael

      1. Hallo,

        Ok, das klärt mein Problem sehr gut, danke.
        Die Methoden sind alle bereits vor dem Erzeugen der Objekte vorhanden

        Nur wenn du mit dem Prototyp arbeitest. Die Funktionsdefinition ist erstmal nur eine Vorlage. Mit der Konstruktormethode new wird ein generisches Objekt erzeugt, dass dann anhand dieser Vorlage um Eigenschaften und Methoden erweitert wird. Innerhalb dieser Vorlage kannst du auf dieses neue Objekt über this zugreifen.
        Wenn du aber in deiner Vorlage keine Zuweisungen vornimmst und einen Prototypen hast der um Eigenschaften und Methoden erweitert wurde, dann wird das Objekt nicht um diese Eigenschaften und Methoden erweitert, sondern es hat einen prototypischen Verweis auf den Prototypen, der wiederum diese Eigenschaften und Methoden hat.

        und werden - wie Du schreibst - mit

        Obj.method = funktion;

        angehängt.
        Somit hat jedes neues Objekt beim Erzeugen bereits alle Funktionen dabei.

        Nein, hier weist du der Instanz (generisches Objekt) die Methode "Irgendwas" zu. Es ist hier nur die entspr. Instanz betroffen.

        bernd

        1. Hi,

          emmmmmmmm - verwirrt ....

          Nur wenn du mit dem Prototyp arbeitest. Die Funktionsdefinition ist erstmal nur eine Vorlage. Mit der Konstruktormethode new wird ein generisches Objekt erzeugt, dass dann anhand dieser Vorlage um Eigenschaften und Methoden erweitert wird. Innerhalb dieser Vorlage kannst du auf dieses neue Objekt über this zugreifen.
          Wenn du aber in deiner Vorlage keine Zuweisungen vornimmst und einen Prototypen hast der um Eigenschaften und Methoden erweitert wurde, dann wird das Objekt nicht um diese Eigenschaften und Methoden erweitert, sondern es hat einen prototypischen Verweis auf den Prototypen, der wiederum diese Eigenschaften und Methoden hat.

          und werden - wie Du schreibst - mit

          Obj.method = funktion;

          angehängt.
          Somit hat jedes neues Objekt beim Erzeugen bereits alle Funktionen dabei.

          Nein, hier weist du der Instanz (generisches Objekt) die Methode "Irgendwas" zu. Es ist hier nur die entspr. Instanz betroffen.

          Also die Funktion, die für das Erzeugen des Objekts zuständig ist, sieht in etwa so aus:

          function NewObject(id){
          // properties:
          this.name = id;
          this.left = 0;
          this.top = 0;
          [etc.]

          // methods:
          this.function1 = ObjFunction1;
          this.function2 = ObjFunction2;
          [etc.]
          }

          nach dem Laden der Seite wird jetzt eine bestimmte Anzahl solcher Objekte erzeugt.

          D = new Array();

          function Startup(){
          for(var i=0; i<10; i++){
          D[i] = new NewObject(i+'id');
          D[i].left = 50;
          [etc.]
          }
          }

          Mit diesem Vorgehen hat doch zunächst einmal das abstrakte Objekt die Methoden und beim Erzeugen der einzelnen Instanzen bekommen diese die dann ebenfalls mit überreicht ?
          Oder denk ich da falsch ?

          Bei dem Prototype dachte ich eigentlich bisher, dass er sich besonders gut eignet, wenn ich für bereits vorhandene Instanzen neue Methoden anfügen will, d.h. mittels prototype bekommt das *abstrakte* Objekt die neue Methode und damit wird sie dann aucht automatisch an alle bereits erzeugten Instanzen weitergereicht ???

          Grüße
          Michael

          1. Hallo,

            Also die Funktion, die für das Erzeugen des Objekts zuständig ist, sieht in etwa so aus:

            function NewObject(id){ // properties: this.name = id; this.left = 0; this.top = 0; [etc.]

            // methods: this.function1 = ObjFunction1; this.function2 = ObjFunction2; [etc.] }

            nach dem Laden der Seite wird jetzt eine bestimmte Anzahl solcher Objekte erzeugt.

            D = new Array();

            function Startup(){ for(var i=0; i<10; i++){ D[i] = new NewObject(i+'id'); D[i].left = 50; [etc.] } }

            Mit diesem Vorgehen hat doch zunächst einmal das abstrakte Objekt die Methoden und beim Erzeugen der einzelnen Instanzen bekommen diese die dann ebenfalls mit überreicht ? Oder denk ich da falsch ?

            Nö, du denkst da schon ganz richtig. Sie (Instanzen) bekommen es (Eigenschaften, Methoden) aber nicht über einen prototypischen Verweis überreicht, sondern werden hier pro Instanz neu zugewiesen, sprich es wird Speicherplatz reserviert etc.

            Beispiel:

            function A() {   this.name = "walter"; }

            var v1 = new A(); var v2 = new A();

            ***************    ***************                             +++++++++++++++

            • A (Instanz) *    * A (Instanz) *  <-- Kopie pro Instanz ---  + A (Vorlage) + ***************    ***************                             +++++++++++++++ name="walter"    name="walter" ***************    ***************    ^                  ^    |                  |    |                  |    v1                 v2

            Bei dem Einsatz von Prototypen ist es anders. Dort gibt es einen Verweis auf ein prototypisches Objekt mit den genannten Eigenschaften und Methoden für alle Instanzen. Der Grund dafür liegt darin, dass der Prototyp bzw. dessen Instanz nicht mitkopiert wird, der Verweis hingegen schon.

            Beispiel:

            function A() {   this.name = "walter"; }

            function B() { } B.prototype = new A();

            var v1 = new B(); var v2 = new B();

            ***************                             +++++++++++++++                    * A (Instanz) *  <-- Kopie pro Instanz ---  + A (Vorlage) +                    ***************                             +++++++++++++++                    name="walter"                    ***************                      |                      #---------- Prototyp (B.prototype = new A();) ---#                      .                                                |                      .                                                |    ....übernommener Verweis....                                       | Verweis    .                          .                                       |    .                          .                                       | ***************    ***************                             +++++++++++++++

            • B (Instanz) *    * B (Instanz) *  <-- Kopie pro Instanz ---  + B (Vorlage) + ***************    ***************                             +++++++++++++++    ^                  ^    |                  |    |                  |    v1                 v2

            Wie du siehst hat weder v1 noch v2, als Instanz gesehen, die Eigenschaft name, sondern teilen sich ein prototypisches Objekt mit der Eigenschaft name ("walter"). Würdest du nun über B.prototype.name den Namen ändern (z.B. "dieter"), dann würde auch v2, da auf die Eigenschaft name über den prototypischen Verweis zugegriffen wird, davon betroffen sein.

            Anders verhält es sich bei einer Zuweisung einer Eigenschaft oder Methode an eine Instanz. Diese wird, weil es sich letztendlich um ein generisches Objekt handelt, dynamisch um die Eigenschaft bzw. Methode erweitert.

            Beispiel:

            function A() {   this.name = "walter"; }

            function B() { } B.prototype = new A();

            var v1 = new B(); var v2 = new B();

            v1.name = "dieter";

            ***************                             +++++++++++++++                    * A (Instanz) *  <-- Kopie pro Instanz ---  + A (Vorlage) +                    ***************                             +++++++++++++++                    name="walter"                    ***************                      |                      #---------- Prototyp (B.prototype = new A();) ---#                      .                                                |                      .                                                |    ....übernommener Verweis....                                       | Verweis    .                          .                                       |    .                          .                                       | ***************    ***************                             +++++++++++++++

            • B (Instanz) *    * B (Instanz) *  <-- Kopie pro Instanz ---  + B (Vorlage) + ***************    ***************                             +++++++++++++++ name="dieter"       ^ ***************       |    ^                  |    |                  |    |                  |    v1                 v2

            Ein alert(v1.name) gibt "dieter" aus, wohingegen ein alert(v2.name) "walter" ausgibt. In Wirklichkeit ist es aber noch wesentlich komplexer, kann aber nicht in einem Post erklärt werden.

            Bei dem Prototype dachte ich eigentlich bisher, dass er sich besonders gut eignet, wenn ich für bereits vorhandene Instanzen neue Methoden anfügen will, d.h. mittels prototype bekommt das abstrakte Objekt die neue Methode und damit wird sie dann aucht automatisch an alle bereits erzeugten Instanzen weitergereicht ???

            Genau, wie die "Grafik" es anschaulich zeigt, teilen sich dann die entspr. Instanzen das prototypische Objekt. Sie verlangen dadurch wesentlich weniger Resourcen und sind in ihrer Erzeugung schneller (Speicherreservierung, Codeauswertung) weil es nur einmal geschieht (für das prototypische Objekt). Sinn mach dies aber wirklich nur bei Methoden, weil diese sich meisten nicht ändern und somit unbedenklich geteilt werden könne, wohingegen Eigenschaften sicherlich für jede Instanz neu gesetzt werden (die Werte).

            Ich hoffe dass ich mich etwas klarer ausgedrückt habe. Falls jemand Fehler sieht möge er mich korrigieren.

            bernd.

            1. Hi Bernd,

              danke für die ausführlichen Infos !

              Viele Grüße
              Michael