Kurt Z: Vererbungshierarchie ?!?

0 67

Vererbungshierarchie ?!?

Kurt Z
  • javascript
  1. 0
    Struppi
    1. 0
      molily
    2. 0
      Don P
      1. 0
        Kurt Z
        1. 0
          Struppi
          1. 0
            Don P
            1. 0
              Struppi
              1. 0
                Don P
                1. 0
                  Struppi
                  1. 0
                    Don P
                    1. 0
                      Struppi
                      1. 0
                        Don P
                        1. 0
                          Struppi
                          1. 0
                            Don P
                      2. 0
                        Kurt Z
                        1. 0
                          Struppi
                          1. 0
                            Kurt Z
                            1. 0
                              Struppi
                              1. 0
                                Kurt Z
                                1. 0
                                  Struppi
                                  1. 0
                                    Kurt Z
                                    1. 0
                                      LanX²
                                    2. 0
                                      Struppi
                                      1. 0
                                        Kurt Z
                                        1. 0
                                          Kurt Z
                                        2. 0
                                          Struppi
                                          1. 0
                                            Kurt Z
                              2. 0
                                Don P
              2. 0
                LanX²
                1. 0

                  Function.prototype.begetObject

                  LanX²
                  1. 0
                    Don P
                    1. 0

                      Knobelaufgabe

                      LanX²
                      1. 0
                        Don P
                    2. 0
                      molily
                      1. 0
                        Kurt Z
                        1. 0

                          Please beget it!

                          LanX²
                          1. 0
                            Kurt Z
                          2. 0
                            Don P
                            1. 0
                              LanX²
                              1. 0
                                Don P
                              2. 0

                                Iterator

                                KurtZ
                                1. 0
                                  LanX
                      2. 0
                        Don P
        2. 0

          new Object(x) statt object(x)

          Kurt Z
          1. 0
            Murphy
            1. 0
              Kurt Z
              1. 0
                Don P
              2. 0
                Murphy
                1. 0
                  Kurt Z
                2. 0
                  molily
  2. 0
    LanX²
  3. 0
    molily
  4. 3

    __proto__ chain

    LanX²
    1. 0
      LanX²
      1. 0
        Kurt Z
    2. 1
      molily
  5. 0

    JS-Version?

    Kurt Z
    1. 0
      Kurt Z
      1. 0
        molily
        1. 0
          molily
    2. 0
      molily
      1. 0
        Kurt Z
        1. 0
          molily
          1. 0
            Kurt Z
  6. 0

    VIELEN DANK!!!

    Kurt Z
    1. 0
      Struppi

Hi

wie funktioniert eigentlich das prototype-Attribut genau?

kleines Beispiel im FF2:

  
function class0() {  
     this.class0 = "SUPER";  
}  
  
  
function class1() {  
     this.class1 = "SUB";  
   }  
  
function instance() {  
    this.instance="EXEMPLAR";  
}  
  
class1.prototype = new class0();  
instance.prototype = new class1();  
  
delete(obj);  
obj = new instance();  
  
out=obj.constructor+"\n";  
for(attr in obj) {  
    out+=attr+": "+obj[attr]+"\n";  
}  
  
alert(out);  

gibt mir brav die komplette vererbungskette aus:

  
function class0() { this.class0 = "SUPER"; }  
instance: EXEMPLAR  
class1: SUB  
class0: SUPER  

vertausche ich aber die prototype-Anweisungen

  
instance.prototype = new class1();  
class1.prototype = new class0();  

bekomme ich nur:
function class1() { this.class1 = "SUB"; }
instance: EXEMPLAR
class1: SUB

Wieso ist die Reihenfolge relevant??? Prototyp wird doch dynamisch ausgewertet...

und wieso ändert sich der constructor???

Ist das jetzt FF spezifisch oder allgemein so dokumentiert?

Kann mir jemand bitte einen guten Link geben wo Vererbungsketten und prototype genau erklärt werden?

Ciao
 Kurt

  1. wie funktioniert eigentlich das prototype-Attribut genau?

    Im Prinzip wie alle anderen Attribute, nur das in dem Moment wo du new Konstruktor() machst, die Instanz die Eigenschaften des Prototype bekommt.

    vertausche ich aber die prototype-Anweisungen

    instance.prototype = new class1();
    class1.prototype = new class0();

    
    >   
    > bekomme ich nur:  
    > function class1() { this.class1 = "SUB"; }  
    > instance: EXEMPLAR  
    > class1: SUB  
      
    Wenn du den prototypen von instance deklarierst, ist class1 noch kein prototype von class0(), das passiert erst danach.  
      
    
    >   
    > Wieso ist die Reihenfolge relevant??? Prototyp wird doch dynamisch ausgewertet...  
      
    genau.  
      
    
    > und wieso ändert sich der constructor???  
      
    Weil der Konstruktor zum Zeitpunkt der prototype Zuweisung class1() ist.  
      
    
    > Kann mir jemand bitte einen guten Link geben wo Vererbungsketten und prototype genau erklärt werden?  
      
    Was Vererbung in JS angeht ist [Douglas Crockford](http://crockford.com/javascript/inheritance.html) empfehlenswert.  
      
    Struppi.
    
    1. Hallo,

      Wenn du den prototypen von instance deklarierst, ist class1 noch kein prototype von class0(), das passiert erst danach.

      Das beantwortet doch die Kernfrage nicht: Wenn in instance.prototype eine Instanz von class1 gespeichert wird, so sollten Änderungen am class1-Prototypen auch auf diese Instanz wirken und also auf die Instanzen von instance.

      Das funktioniert auch durchaus, nur dann nicht, wenn man das prototype-Objekt überschreibt.

      Statt
      class1.prototype = { class0 : "SUPER" }; (was äquivalent zu new class0() ist, Vererbung mal außen vor)
      kann ich
      class1.prototype.class0 = "SUPER";
      notieren, und das wirkt sich dann auf alle instance-Instanzen aus. Warum?

      So könnte ich einfach alle Member von new class0 mit einer for-in-Schleife nach class1.prototype kopieren und das Problem wäre gelöst. Nachträgliche Änderungen an class0.prototype werden dann natürlich nicht berücksichtigt. Mehrfach-Vererbung, bei der ich nachträglich alle möglichen Prototypen in der Hierarchie ändern kann, geht wohl einfach nicht.

      Mathias

    2. Hallo,

      Was Vererbung in JS angeht ist Douglas Crockford empfehlenswert.

      Crockford beschreibt dort, wie die klassische Vererbung mit JavaScript umgesetzt wird. Mir persönlich (und auch ihm) gefällt inzwischen der weitgehende Verzicht auf Konstruktoren besser, wie in seinem Artikel Prototypal Inheritance in JavaScript beschrieben.

      @Krt Z:

      Zur Verdeutlichung folgendes Beispiel:
      *** Klassische Vererbung: ***************************************************

        
        
      var  
          Ort = function () {},  
          Chef = function () {},  
        
          Ort1 = function () { this.ort = "Ort 1" },  
          Chef1 = function () { this.name = "Ferengi" },  
        
          Ort2 = function () { this.ort = "Ort 2" },  
          Chef2 = function () { this.name = "Mensch" },  
        
          statusQuo = function () {  
        
              var welt = new Ort(); welt.chef = new Chef();  
              alert( welt.ort + ' wird beherrscht von der Spezies ' + welt.chef.name );  
          }  
      ;  
        
        
      Ort.prototype = new Ort1();  
      Chef.prototype = new Chef1();  
      statusQuo();  
        
      Ort.prototype = new Ort2();  
      Chef.prototype = new Chef2();  
      statusQuo();  
        
      // Die Außerirdischen kommen:  
      Chef.prototype = new Chef1();  
      statusQuo();
      

      *** Reine prototypische Vererbung nach Crockford: ********************************

        
        
      var object = function(o){function F(){}F.prototype=o;return new F();}; // Crockford  
        
      var  
          Ort = {},  
          Chef = {},  
        
          Ort1 = { ort: "Ort 1" },  
          Chef1 = { name: "Ferengi" },  
        
          Ort2 = { ort: "Ort 2" },  
          Chef2 = { name: "Mensch" },  
        
          statusQuo = function () {  
        
              var welt = Ort;  
              welt.chef = Chef;  
              alert( welt.ort + ' wird beherrscht von der Spezies ' + welt.chef.name );  
          }  
      ;  
        
      Ort = object(Ort1);  
      Chef = object(Chef1);  
      statusQuo();  
        
      Ort = object(Ort2);  
      Chef = object(Chef2);  
      statusQuo();  
        
      // Die Außerirdischen kommen:  
      Chef = object(Chef1);  
      statusQuo();
      

      ****************************************************************************

      Wie man sieht, leisten beide Versionen das gleiche, aber die zweite Variante kommt wesentlich schlanker und m.M.n. schöner daher, weil auf die ständige Wiederholung der Schlüsselwörter new, function, this und prototype verzichtet werden kann.

      Selber habe ich dann Crockfords genialer Funktion "object" noch eine weitere zur Seite gestellt, die es erlaubt ein Objekt zu klonen, d.h. nicht nur ein neues, eigentlich leeres Objekt mit den gleichen Eigenschaften zu erhalten (die eigentlich nur vom Prototyp "durchscheinen") wie bei Crockford, sondern otional auch ein Objekt, das alle oder auch nur gewisse Eigenschaften wirklich selbst hat. Man gibt einfach als zweiten Parameter ein Objekt an, dessen Eigenschaften/Methoden das neue Objekt dann selbst haben soll. Das können auch zusätzliche Eigenschaften/Methoden sein, die das Ursprungsobjekt nicht hatte.

      Gruß, Don P

      --
      sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
      1. Hallo Don,

        Mir persönlich (und auch ihm) gefällt inzwischen der weitgehende Verzicht auf Konstruktoren besser, wie in seinem Artikel Prototypal Inheritance in JavaScript beschrieben.

        Danke für den Link, das befreit mich jetzt von dem Missverständnis JS wäre eine typische prototyp-basierte Sprache. Ich konnte bisher die Abgrenzung zu Klassen-basierten Sprachen nicht ganz nachvollziehen.[1]

        Allerdings, eines stört mich an dieser object() Vererbungsfunktion...

        var object = function(o){function F(){}F.prototype=o;return new F();};

        ... wo bleibt dann der Konstruktor für lokale Variablen der Instanz (this.bla usw...)? (da fehlt ein Semikolon oder?)  
          
        oder gibts auch ne art 2 parametrige Version?  
        (ungetestet)  
        ~~~javascript
          
        var object = function(o,F){  
             if (! F) function F(){};  
             F.prototype=o;  
             return new F();  
        };  
        
        

        So kann man wirklich weitestgehend auf new und prototype verzichten, function und this wird man aber trotzdem zumindest für Methoden brauchen.

        Ciao
         Kurt

        [1] naja von Perl bin ich auch ein verwirrend vielfältiges Objektsystem, sowie Closures und Coderefrenzen gewohnt, die man braucht man in JS um javaartige Klassen abzubilden.

        1. Allerdings, eines stört mich an dieser object() Vererbungsfunktion...

          var object = function(o){function F(){}F.prototype=o;return new F();};

          
          > ... wo bleibt dann der Konstruktor für lokale Variablen der Instanz (this.bla usw...)? (da fehlt ein Semikolon oder?)  
            
          Nein, es fehlt kein Semikolon. Das ist das Problem an diesem Konstrukt, es ist keine allgemein Funktion um eine Vererbung darzustellen, sondern ist nur ein Beispiel für die Vererbung von F(), d.h. du musst für jedes unterschiedliche F() das vererben soll, eine solche Funktion schreiben. Das ist auch die einzige Möglichkeit sinnvolle Vererbung in JS umzusetzten.  
            
          
          > So kann man wirklich weitestgehend auf new und prototype verzichten, function und this wird man aber trotzdem zumindest für Methoden brauchen.  
            
          Der Verzicht auf prototype ist nur bedingt, du verschiebst einfach die Verwendung von prototype in die object() Funktion.  
            
          
          > [1] naja von Perl bin ich auch ein verwirrend vielfältiges Objektsystem, sowie Closures und Coderefrenzen gewohnt, die man braucht man in JS um javaartige Klassen abzubilden.  
            
          Naja, so verwirrend finde ich Perl nicht, solange man sich nicht in die Innereien von Perl wagt und für javartige Klassen einfach die entsprechenden Module verwendet. Aber ich gebe es zu, ich habe auch erstmal [Class::Accessor](http://search.cpan.org/~kasei/Class-Accessor-0.31/lib/Class/Accessor.pm) nachgebaut, bevor ich beim CPAN gesucht hatte.  
            
          Struppi.
          
          1. Hallo,

            Allerdings, eines stört mich an dieser object() Vererbungsfunktion...

            var object = function(o){function F(){}F.prototype=o;return new F();};

            
            > > ... wo bleibt dann der Konstruktor für lokale Variablen der Instanz (this.bla usw...)? (da fehlt ein Semikolon oder?)  
            >   
            > Das ist das Problem an diesem Konstrukt, es ist keine allgemein Funktion um eine Vererbung darzustellen, sondern ist nur ein Beispiel für die Vererbung von F(), d.h. du musst für jedes unterschiedliche F() das vererben soll, eine solche Funktion schreiben.  
              
            Aber nein, dann wäre das Ding ja wertlos. Es ist vielmehr ein allgemeiner Konstruktor, der von jedem beliebeigen Objekt ein neues konstruieren kann.  
              
            Statt einen Kontruktor zu notieren, und dann ein Objekt daraus zu erstellen mit z.B.  
              
            ~~~javascript
              
            var obj = function () {  
              this.property = value;  
            }  
            var newObj = new obj();
            

            notiert man nur das Objekt und überlässt der Konstruktorfunktion "object" das erstellen des neuen Objekts:

              
            var obj = {  
              property: value;  
            }  
            var newObj = object(obj);
            

            Das funktioniert natürlich auch mit einem expliziten Konstruktor obj wie oben, wenn man das unbedingt will, was aber unsinnig ist:

              
            var obj = function () {  
              this.property = value;  
            }  
            var newObj = object(obj);  
            
            

            Das ist auch die einzige Möglichkeit sinnvolle Vererbung in JS umzusetzten.

            JS *ist* eben eien Prorotyp-basierte Sprache. Das Hantieren mit Konstruktoren und Klassen ist zwar möglich, aber umständlich und nicht wirklich nötig.

            So kann man wirklich weitestgehend auf new und prototype verzichten, function und this wird man aber trotzdem zumindest für Methoden brauchen.

            Ganz ohne diese geht es nicht, man braucht sie aber nicht mehr für Kontruktoren.

            Der Verzicht auf prototype ist nur bedingt, du verschiebst einfach die Verwendung von prototype in die object() Funktion.

            Klar, was aber ein großer Vorteil ist, weil man new und prototype dann nur noch an einer einzigen Stelle, nämlich in der Konstruktorfunktion "object" notieren muss. Ansonsten ist man für alle Zeit davon befreit.

            Gruß, Don P

            1. Das ist das Problem an diesem Konstrukt, es ist keine allgemein Funktion um eine Vererbung darzustellen, sondern ist nur ein Beispiel für die Vererbung von F(), d.h. du musst für jedes unterschiedliche F() das vererben soll, eine solche Funktion schreiben.

              Aber nein, dann wäre das Ding ja wertlos. Es ist vielmehr ein allgemeiner Konstruktor, der von jedem beliebeigen Objekt ein neues konstruieren kann.

              Das ist schon klar, das Problem ist aber wenn ich im Kontruktor Parameter brauche, was dann?

              var obj = function(name) {  
                this.name = name || 'default';  
              }  
              var newObj = object(obj);  
              var newObj2 = object(obj);  
              alert( newObj.name + '\n' + newObj2.name );  
              
              

              Struppi.

              1. Hallo,

                Das ist schon klar, das Problem ist aber wenn ich im Kontruktor Parameter brauche, was dann?

                var obj = function(name) {

                this.name = name || 'default';
                }
                var newObj = object(obj);
                var newObj2 = object(obj);
                alert( newObj.name + '\n' + newObj2.name );

                  
                Wer macht denn sowas ;-)  
                  
                Das ist ja kein "normaler" Konstruktor mehr, sondern einer, der das zu erzeugende Objekt zuerst aus Parametern zusammenbasteln muss. Für solche speziellen Fälle kann man ja weiterhin mit Konstuktoren und "new" arbeiten.  
                  
                Oder man bastelt sich (wie ich) eine weitere kleine Helferfunkrion:  
                  
                ~~~javascript
                  
                      var object = function(o){function F(){}F.prototype=o;return new F();};  
                      var oobject = function(s,t){var c=object(s);for(var p in t){c[p]=t[p];}return c;}  
                  
                      var obj = {  
                  
                          name: 'default'  
                      }  
                  
                      var newObj = object(obj);  
                      var newObj2 = object(obj);  
                      alert( newObj.name + '\n' + newObj2.name );      // 2 mal 'default' vom Prototyp  
                  
                      var newObj = oobject(obj, {name: 'Rumpelstilz'});  
                      var newObj2 = oobject(obj, {name: 'Königin'});  
                      alert( newObj.name + '\n' + newObj2.name );     //'Rumpelstilz', 'Königin' von eigenen Eigenschaften  
                  
                      delete newObj.name;                             // eigene Eigenschaft wieder entfernen  
                      alert( newObj.name + '\n' + newObj2.name );     // 'default' vom Prototyp, 'Königin' von eigener Eigenschaft  
                
                

                Als zweiten Parameter übergibt man "oobject" einfach ein Objekt, dessen Eigenschaften/Methoden das neue Objakt dann selbst haben soll, d.h. diese überschreiben den Wert vom Prototyp, bzw. eigentlich verstecken sie ihn nur. Wenn man wie im Beispiel so eine eigene Eigenschaft dann wieder entfernt, scheint wieder der Prototyp durch.

                Um z.B. ein Objekt zu klonen, das alle Eigenschaften selbst hat, notiert man einfach: var newObj = oobject(obj, obj);

                Gruß, Don P

                --
                sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
                1. Wer macht denn sowas ;-)

                  Das ist ja kein "normaler" Konstruktor mehr, sondern einer, der das zu erzeugende Objekt zuerst aus Parametern zusammenbasteln muss. Für solche speziellen Fälle kann man ja weiterhin mit Konstuktoren und "new" arbeiten.

                  Ich halte das nicht für speziell, im gegenteil ich verwende sowas sehr häufig und muss genau aus dem Grund für jedes Objekt das ich verwende eine eigene object() Funktion schreiben mit den nötigen Parametern.

                  Oder man bastelt sich (wie ich) eine weitere kleine Helferfunkrion:

                  Was in etwa der ersten von Douglas Crockford vorgeschlagenen Möglichkeit entspricht.

                  var newObj = oobject(obj, {name: 'Rumpelstilz'});
                        var newObj2 = oobject(obj, {name: 'Königin'});

                  Naja, mir wäre das zu umständlich, da ich es wie gesagt häufig brauche.

                  Struppi.

                  1. Hallo,

                    Ich halte das nicht für speziell, im gegenteil ich verwende sowas sehr häufig und muss genau aus dem Grund für jedes Objekt das ich verwende eine eigene object() Funktion schreiben mit den nötigen Parametern.

                    Das machst du aber nicht wirklich, oder?

                    Oder man bastelt sich (wie ich) eine weitere kleine Helferfunkrion:

                    Was in etwa der ersten von Douglas Crockford vorgeschlagenen Möglichkeit entspricht.

                    Welche jetzt? Meinst du den Artikel über klassische Vererbung? Dann verstehe ich das nicht.

                    var newObj = oobject(obj, {name: 'Rumpelstilz'});
                          var newObj2 = oobject(obj, {name: 'Königin'});

                    Naja, mir wäre das zu umständlich, da ich es wie gesagt häufig brauche.

                    Mit vielen Parametern? Ab einer gewissen Menge an Parametern empfiehlt sich ohnehin die Übergabe als Objekt, weil man sich dabei keine besondere Reihenfolge merken muss und immer gleich sieht, welcher Parameter was ist. Das zweite übergebene Objekt muss auch nicht unbedingt literal notiert werden, es kann ja auch eine Referenz auf ein anderes Objekt sein.

                    Für nur wenige Parameter finde ich das nicht wirklich umständlich. Darüberhinaus kann das zweite übergebene Objekt auch andere oder zusätzliche Eigenschaften/Methoden haben, die das Ausgangsobjekt nicht hat, das neu erzeugte dann aber schon. Wie würdest du sowas dann mit einfacher Parameterübergabe lösen?

                    Gruß, Don P

                    --
                    sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
                    1. Ich halte das nicht für speziell, im gegenteil ich verwende sowas sehr häufig und muss genau aus dem Grund für jedes Objekt das ich verwende eine eigene object() Funktion schreiben mit den nötigen Parametern.

                      Das machst du aber nicht wirklich, oder?

                      Natürlich.

                      Hier mal ein etwas hypothetisches Beispiel eines DOM Elementes.

                      function MyBaseObject(id, p) {  
                       var obj = document.getElementById(id) || { id:id};  
                       var parent = p;  
                       this.id = function() {return obj.id;}  
                      }  
                        
                      function MyChildObject(id, c) {  
                       function F() {  
                        var color = c;  
                        this.getColor = function() { return color;}  
                       }  
                       F.prototype = new MyBaseObject(id, this);  
                       return new F();  
                      }  
                        
                      var o1 = new MyChildObject('test_1', 'red');  
                      var o2 = new MyChildObject('test_2', 'green');  
                      alert(o1.id())  
                      alert(o2.id())
                      

                      Wie würde ich das mit der Kontruktorfunktion schreiben?

                      Struppi.

                      1. Hallo,

                        Hier mal ein etwas hypothetisches Beispiel eines DOM Elementes.

                        Das ist ziemlich trickreich mit Closures und allem. Die Variable parent wird nicht weiter verwendet, Absicht?

                        Wie würde ich das mit der Konstruktorfunktion schreiben?

                        Naja, dafür muss man doch gar keinen Konstruktor bemühen, sondern kann es einfach so notieren (wenn MyChildObject denn unbedingt ein Objekt mit genau zwei Methoden zurückgeben soll und unter Verzicht auf MyBaseObject sowie die unbenutzte Variable parent):

                          
                            function MyChildObject(id, c) {  
                          
                                return {  
                                         id: function() { return (document.getElementById(id) || {id:id}).id; },  
                                         getColor: function () { return c; }  
                                       };  
                            }  
                          
                            var o1 = MyChildObject('test_1', 'red');  
                            var o2 = MyChildObject('test_2', 'green');  
                          
                            alert(o1.id()); alert(o1.getColor());  
                            alert(o2.id()); alert(o2.getColor());
                        

                        Oder, wenn MyBaseObject totzdem mitspielen soll (aber ohne parent), z.B. so:

                          
                          
                            function MyBaseObject(id) {  
                          
                                var obj = document.getElementById(id) || { id:id};  
                                return {id: function() {return obj.id;} };  
                            }  
                          
                            function MyChildObject(id, c) {  
                          
                                return {  
                                         id: MyBaseObject(id).id,  
                                         getColor: function () { return c; }  
                                       };  
                            }
                        

                        Die Variable parent hast du Schlingel ;-) wohl absichtlich als besonderen Stolperstein eingebaut. Auch das sollte sich aber lösen lassen, denke ich mal.

                        Wegen der Closures würde es mit der Konstruktorfunktion wohl eher kompliziert aussehen. Vielleicht finde ich noch Zeit, es mal umzusetzen, mitsamt parent.

                        Gruß, Don P

                        1. Hier mal ein etwas hypothetisches Beispiel eines DOM Elementes.

                          Das ist ziemlich trickreich mit Closures und allem. Die Variable parent wird nicht weiter verwendet, Absicht?

                          Ich hab hier noch ein komplexeres Beispiel ;-)

                          Ich denke konkret an Objekte um das DOM zu manipulieren und/oder Elemente zu erzeugen bzw. löschen. Da ist ein parent u.U. notwendig, wobei das this hier wohl eher Blödsinn ist.

                          Wie würde ich das mit der Konstruktorfunktion schreiben?

                          ...

                          Oder, wenn MyBaseObject totzdem mitspielen soll (aber ohne parent), z.B. so:

                          Ja, das sollte existieren, da ich ja mehrere unterschiedliche Objekte davon erben lassen will.

                          function MyBaseObject(id) {

                          var obj = document.getElementById(id) || { id:id};
                                  return {id: function() {return obj.id;} };
                              }

                          function MyChildObject(id, c) {

                          return {
                                           id: MyBaseObject(id).id,
                                           getColor: function () { return c; }
                                         };
                              }

                            
                          Hmm, das ist so nicht gewollt, die Funktion id ist nur ein Beispiel, MyBaseObjekt() soll/kann natürlich mehrere Methoden haben, die vererbt werden sollen  
                            
                          
                          > Die Variable parent hast du Schlingel ;-) wohl absichtlich als besonderen Stolperstein eingebaut.  
                            
                          Nicht wirklich ;-)  
                          Ich hab da eher an was falsches gedacht (s.o).  
                            
                          
                          > Wegen der Closures würde es mit der Konstruktorfunktion wohl eher kompliziert aussehen. Vielleicht finde ich noch Zeit, es mal umzusetzen, mitsamt parent.  
                            
                          das ist ja der Punkt, mir leuchtet der Sinn von der Funktion object() nicht ein, da ich so einfache Konstrukte nicht habe, wenn ich mit Vererbung arbeite.  
                            
                          Es kann aber auch durchaus sein, dass ich immer noch nicht 100% hinter OOP steige, da ich nie was mit Java gemacht habe und insofern wenig Ahnung von Klassen und Vererbung habe.  
                            
                          Struppi.
                          
                          1. Hallo,

                            Ich hab hier noch ein komplexeres Beispiel ;-)

                            Stöhn... Danke, dass du es nicht gepostet hast ;-)

                            Ich denke konkret an Objekte um das DOM zu manipulieren und/oder Elemente zu erzeugen bzw. löschen. Da ist ein parent u.U. notwendig, wobei das this hier wohl eher Blödsinn ist.

                            Interessant, vielleicht sollest du doch mal konkreteres posten. Vielleicht fällt mir sogar was brauchbares dazu ein, könnte auch mir nützen.

                            Oder, wenn MyBaseObject totzdem mitspielen soll (aber ohne parent), z.B. so:
                            ...
                            Ja, das sollte existieren, da ich ja mehrere unterschiedliche Objekte davon erben lassen will.
                            ...
                            Hmm, das ist so nicht gewollt, die Funktion id ist nur ein Beispiel, MyBaseObjekt() soll/kann natürlich mehrere Methoden haben, die vererbt werden sollen

                            Dann kann man das ganz analog z.B. so machen:

                              
                                function MyBaseObject(id, c) {  
                              
                                    var obj = document.getElementById(id) || {id:id};  
                                    obj.itsColor = c;  
                                    obj.methode1 = function () {...};  
                                    obj.methode2 = function () {...};  
                                    obj.eigenschaft1 = obj.id.getElementsByTagName('th');  
                                    // usw.  
                              
                                    return obj;  
                                }
                            

                            Eine Notwendigkeit für Vererbung kann ich da noch immer nicht sehen. Man muss ja nicht um jeden Preis vererben. Besser ist zur Laufzeit schenken, kostet weniger Steuern ;-) Mit ein bisschen Vererbung ginge das das z.B. so:

                              
                                function MyBaseObject(id, c) {  
                              
                                    var  
                                        obj = document.getElementById(id),  
                                        erweiterung = {  
                                                       itsColor: c,  
                                                       methode1: function () {return "e1";},  
                                                       methode2: function () {return "e2";},  
                                                       eigenschaft1: obj.getElementsByTagName('th')  
                                                       // usw.  
                                       }  
                                    ;  
                                    return oobject(obj,erweiterung);  
                                }
                            

                            das ist ja der Punkt, mir leuchtet der Sinn von der Funktion object() nicht ein, da ich so einfache Konstrukte nicht habe, wenn ich mit Vererbung arbeite.

                            Du könntest aber höchstwahrscheinlich deine komplexeren Konstrukte auf einfache herunterbrechen. Z.B. machst du intensiven Gebrauch von Closures. Warum eigentich? Wie wir gesehen haben, braucht man die für diesen Zweck gar nicht. Ich finde, das verkompliziert die Sache nur.

                            Es kann aber auch durchaus sein, dass ich immer noch nicht 100% hinter OOP steige, da ich nie was mit Java gemacht habe und insofern wenig Ahnung von Klassen und Vererbung habe.

                            Ich auch nicht wirklich, hehe. Das ist doch eine hervorragende Ausgangsbasis, um den ganzen Ballast von Klassen und Konstruktoren rechts zu überholen und gleich auf dem aktuellen Stand der Technik einzusteigen, jedenfalls in JavaScript. Späteres Umdenken wäre sicher schwerer.

                            Gruß, Don P

                            --
                            sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
                      2. Hi

                        function MyBaseObject(id, p) {

                        var obj = document.getElementById(id) || { id:id};
                        var parent = p;
                        this.id = function() {return obj.id;}
                        }

                        function MyChildObject(id, c) {
                        function F() {
                          var color = c;
                          this.getColor = function() { return color;}
                        }
                        F.prototype = new MyBaseObject(id, this);
                        return new F();
                        }

                        var o1 = new MyChildObject('test_1', 'red');
                        var o2 = new MyChildObject('test_2', 'green');
                        alert(o1.id())
                        alert(o2.id())

                        
                        >   
                        > Wie würde ich das mit der Kontruktorfunktion schreiben?  
                        >   
                          
                        um das zu beantworten müsste man deinen Code erst verstehen ...  
                          
                        Die Funktion  MyChildObject retuniert  eine Instanz des Konstruktor MyBaseObject. Aber statt  
                          
                        var o1 = MyChildObject('test\_1', 'red');  
                          
                        schreibst du  
                          
                        var o1 = new MyChildObject('test\_1', 'red');  
                          
                        d.h. für du erzeugst in o1 eine Instanz von MyChildObject, und bei der Konstruktion wird eine Instanz von MyBaseObject returniert.  
                          
                        Was passiert sinnvolles mit dem Returnvalue einer Konstruktion ?!?  
                          
                        Ich bin ziemlich ratlos ... erklär mal was das bewirkt.  
                          
                        Kurt
                        
                        1. um das zu beantworten müsste man deinen Code erst verstehen ...

                          Die Funktion  MyChildObject retuniert  eine Instanz des Konstruktor MyBaseObject. Aber statt

                          var o1 = MyChildObject('test_1', 'red');

                          schreibst du

                          var o1 = new MyChildObject('test_1', 'red');

                          Stimmt, das war Dummheit (ich merk das auch erst jetzt und hab das tatsächlich so öfters in meinem Code, Danke für den Hinweis) aber es geht auch ohne, bzw. ist natürlich sinnvoller ohne new

                          Ich bin ziemlich ratlos ... erklär mal was das bewirkt.

                          Tut mir leid.

                          Also ich hab ein Basisobjekt von dem ein Objekt erbt. Der (Dummy)Aufruf von document.getElementById() soll nur zeigen wo ich sowas einsetze.

                          Struppi.

                          1. Hi

                            Und das funktioniert trotzdem? Kopfkratz ...

                            MyChildObject würde ich kleinschreiben, ist ja kein Konstruktor.

                            vielleicht makeChildObject?

                            Bye
                             Kurt

                            1. Und das funktioniert trotzdem? Kopfkratz ...

                              Ja, der Rückgabewert wird bei new verworfen.

                              MyChildObject würde ich kleinschreiben, ist ja kein Konstruktor.

                              vielleicht makeChildObject?

                              Im Prinzip hast du Recht, liegt wohl an dem was ich Don schon geschrieben habe und meiner Blödheit solche Funktionen immer mit new aufzurufen. Auch wenn jetzt die Frage noch nicht geklärt ist, was mir die Funktion object() bringt, hat mir das auf jeden Fall schon mal geholfen.

                              Struppi.

                              1. Hi

                                Ja, der Rückgabewert wird bei new verworfen.

                                Ich dachte um den Rückgabewert gehts? Also ich versuche mich nicht daran dass umzusetzen, sorry das ist für mich Obfuscation.

                                Auch wenn jetzt die Frage noch nicht geklärt ist, was mir die Funktion object() bringt, hat mir das auf jeden Fall schon mal geholfen.

                                Nun, vielleicht stehts in seinem neuen Buch das im Mai bei O'Reilly rauskommt.
                                Spannend, ob LanX's Verbesserungsvorschlag mit reinkommt :)

                                Tschau
                                 Kurt

                                1. Ja, der Rückgabewert wird bei new verworfen.

                                  Ich dachte um den Rückgabewert gehts? Also ich versuche mich nicht daran dass umzusetzen, sorry das ist für mich Obfuscation.

                                  Nein, es geht um die Vererbung und um die hier im thread gezeigte Funktion, deren Einsatzzwecke mir nicht klar ist.

                                  So Obfuscation ist das gar nicht, das die gleiche Arbeitsweise wie in der Funktion von Douglas Crockford (eine vernüftige Vererbungshierachie ist in JS auch kaum zu erreichen)

                                  Struppi.

                                  1. Hi

                                    VERMUTUNG: Geht es nur darum einen Erben mit einem privaten Read-Only-Wert Color zu bauen?

                                    Er sagt IMHO selbst dass er für private Attribute auf spezielle "Maker" ausweicht, ohne diese zu präzisieren.

                                    Ich würds vielleicht so machen:

                                      
                                    function object (o){  
                                      function F(){}  
                                      F.prototype=o;  
                                      return new F();  
                                    };  
                                      
                                    function maker (o,color){  
                                      var child=object(o);  
                                      child.Color=function (){return color};  
                                      return child;  
                                    };  
                                      
                                    x={a:1};  
                                    y=maker(x,"blau");  
                                    z=maker(x,"grün");  
                                    alert(y.Color()+z.Color()+y.color); //blaugrünundefined  
                                    
                                    
                                    1. Hallo

                                      function object (o){
                                        function F(){}
                                        F.prototype=o;
                                        return new F();
                                      };

                                      function maker (o,color){
                                        var child=object(o);
                                        child.Color=function (){return color};
                                        return child;
                                      };

                                      x={a:1};
                                      y=maker(x,"blau");
                                      z=maker(x,"grün");
                                      alert(y.Color()+z.Color()+y.color); //blaugrünundefined

                                        
                                      sieht doch recht schick aus, außerdem könnte man sich einen generischen "MakerMaker" konstruieren, der als 2.Parameter ein Hasharray erhält der Form  
                                        
                                      { ro: [ ["color",color],  ... ],  /\* Read-Only   \*/  
                                        rw: [ ["name" ,name ] , ...],   /\* Read-Write  \*/  
                                        ...  
                                      }  
                                        
                                      und einen Maker erzeugt der  Getter und Setter automatisch generiert.  
                                        
                                        
                                      So long  
                                        LanX
                                      
                                    2. Ich würds vielleicht so machen:

                                      function object (o){
                                        function F(){}
                                        F.prototype=o;
                                        return new F();
                                      };

                                      function maker (o,color){
                                        var child=object(o);
                                        child.Color=function (){return color};
                                        return child;
                                      };

                                      x={a:1};
                                      y=maker(x,"blau");
                                      z=maker(x,"grün");
                                      alert(y.Color()+z.Color()+y.color); //blaugrünundefined

                                        
                                      Was mir hier noch fehlt ist ein setter für die private Variabel color, ausserdem wollte ich dem Basisobjekt (das bei dir a heißt) einen Parameter übergeben.  
                                        
                                      ~~~javascript
                                      function MyBaseObject(id) {  
                                       var obj = document.getElementById(id) || {style: {}};  
                                        
                                       this.obj = function() {return obj;}  
                                       this.setStyle = function(name, value) { obj.style[name] = value;};  
                                      }  
                                        
                                      function MyChildObject(id, c) {  
                                       function F() {  
                                        var color = c;  
                                        this.getColor = function() { return color;}  
                                        this.setColor = function(c) { color = c; this.setStyle('color', c); return color;}  
                                       }  
                                       F.prototype = new MyBaseObject(id);  
                                       return new F();  
                                      }  
                                        
                                      var o1 = new MyChildObject('test_1', 'red');  
                                      var o2 = new MyChildObject('test_2', 'green');  
                                      o1.setColor('blue');  
                                      alert(o1.getColor() );  
                                      
                                      

                                      Die Frage von mir war ja, wie kann ein komplexeres Objekt (mein Beispiel ist noch relativ einfach), mit dieser Funktion erzeugen.

                                      Struppi.

                                      1. Hi Struppi,

                                        Die Frage von mir war ja, wie kann ein komplexeres Objekt (mein Beispiel ist noch relativ einfach), mit dieser Funktion erzeugen.

                                        Naja ... wenn Crockford argumentiert sein Stil wäre lesbarer, dann hast du es ja gerade bewiesen. Deine Vorlage war IMHO schwer zu lesen, undokumentiert und zudem fehlerhaft.

                                        Aber diese neue Vorlage ist schon deutlich weniger überladen:

                                        function MyChildObject(id, c) {
                                        function F() {
                                          var color = c;
                                          this.getColor = function() { return color;}
                                          this.setColor = function(c) { color = c; this.setStyle('color', c); return color;}
                                        }
                                        F.prototype = new MyBaseObject(id);
                                        return new F();
                                        }

                                        Was mir hier noch fehlt ist ein setter für die private Variabel color,

                                        Na genau analog zum getter zu schreiben, die makeFunktion liefert dir den Scope  für die Closures die normalerweise von der constructorFunktion käme, um private Variablen und Funktionen zu realisieren. Eventuell noch zusätzlich ein

                                        var color = c;

                                        damit der setter die Variable findet. (theoretisch gehts aber ohne)

                                        ausserdem wollte ich dem Basisobjekt (das bei dir a heißt) einen Parameter übergeben.

                                        [code lang=javascript]function MyBaseObject(id) {
                                        var obj = document.getElementById(id) || {style: {}};

                                        this.obj = function() {return obj;}
                                        this.setStyle = function(name, value) { obj.style[name] = value;};
                                        }

                                          
                                        ungetestet:  
                                          
                                        ~~~javascript
                                          
                                        function makeBaseObject(id) {  
                                          var  that={};  
                                          var  node = document.getElementById(id) || {style: {}};  
                                          that.getNode = function() {return node;} ;  
                                          that.setStyle = function(name, value) { obj.style[name] = value;};  
                                          return that;  
                                        }  
                                        
                                        

                                        ich habe mal deine Namensgebung lesbarere gemacht, man sollte nicht alles obj nennen.

                                        OK so?

                                        gruß
                                         Kurt

                                        1. Fehler im Umbennenen

                                          statt

                                          that.setStyle = function(name, value) { obj.style[name] = value;};

                                          besser

                                          that.setStyle = function(name, value) { node.style[name] = value;};

                                          Kurt

                                        2. Die Frage von mir war ja, wie kann ein komplexeres Objekt (mein Beispiel ist noch relativ einfach), mit dieser Funktion erzeugen.

                                          Naja ... wenn Crockford argumentiert sein Stil wäre lesbarer, dann hast du es ja gerade bewiesen. Deine Vorlage war IMHO schwer zu lesen, undokumentiert und zudem fehlerhaft.

                                          Es war keine Vorlage sondern ein undokumentiertes, in meinen Augen triviales Beispiel. Zudem war es nach dem gleichen System wie die Funktion von Crockford (da wie schon erwähnt, Vererbung mit JS nur schwer möglich ist), insofern hätte ich nicht soviele Schwierigkeiten das nachzuvollziehen erwartet.

                                          Und das Problem war, ich konnte mein System nicht auf das Crockford'sche System übertragen. Jetzt aber schon und ich glaube so langsam zu verstehen, was daran besser ist. Muss mir das aber noch mal in aller Ruhe in einer konkreten Umgebung anschauen.

                                          ich habe mal deine Namensgebung lesbarere gemacht, man sollte nicht alles obj nennen.

                                          Man bist du Pingelig, es ist ein Beispiel, ausserdem man sollte einen getter auch nicht mit Großbuchstaben beginnen - so!

                                          OK so?

                                          Ja, danke soweit.

                                          Struppi.

                                          1. Hi

                                            Man bist du Pingelig, es ist ein Beispiel,

                                            Sorry, ich habs wirklich nicht verstanden!

                                            ausserdem man sollte einen getter auch nicht mit Großbuchstaben beginnen - so!

                                            Naja ich hatte mir schon was dabei gedacht, Color sollte ein Kombi aus Getter und Setter werden ("Mutator" ?), und ich wollte es von einem eventuellem Attribut color unterscheiden können, aber das würde zu weit führen.

                                            Was ich noch vermisse, udn was in JS wohl auch nicht einfach zu realisieren ist (Perl auch nicht), ist es unzulässige Attribute auszuschließen.

                                            Wenn man versehentlich Node.color="green" (statt Node.color("green")) schreibt und color gar nicht existiert gibts keine Fehlermeldung udn man muss debuggen.

                                            bye
                                             Kurt

                              2. Hallo Struppi,

                                Auch wenn jetzt die Frage noch nicht geklärt ist, was mir die Funktion object() bringt, hat mir das auf jeden Fall schon mal geholfen.

                                Zum Sinn der Funktion object() kann ich die noch folgendes Beispiel geben, das die direkte Vererbung demonstriert. Die (ebenfalls von Crockford übernommene) Funktion typeOf() dient hier lediglich dazu, JavaScript's unzureichende Auskunft typeof [] === 'object' zu umgehen, object() ist ja die bereits bekannte Funktion:

                                  
                                var typeOf = function (v){var s=typeof v;if(s!=='object'){return s;}if(!v){return'null';}if(typeof v.length==='number'&&!(v.propertyIsEnumerable('length'))&&typeof v.splice==='function'){return'array';}return s;};  
                                var object = function(o){function F(){}F.prototype=o;return new F();};  
                                  
                                var array = [5,6,7,8,9],  
                                    copy1 = object(array),  
                                    copy2 = object(copy1)  
                                ;  
                                  
                                alert([ typeOf(array), typeOf(copy1), typeOf(copy2) ]); // array,array,array  
                                  
                                alert([ array[3], copy1[3], copy2[3] ]); // 8,8,8  
                                  
                                copy1[3] = 80;  
                                alert([ array[3], copy1[3], copy2[3] ]); // 8,80,80  
                                  
                                copy2[3] = 800;  
                                alert([ array[3], copy1[3],  copy2[3] ]); // 8,80,800  
                                  
                                delete copy2[3];  
                                alert([ array[3], copy1[3], copy2[3] ]); // 8,80,80  
                                  
                                delete copy1[3];  
                                alert([ array[3], copy1[3], copy2[3] ]); // 8,8,8
                                

                                Jedes Array erbt direkt vom Vorgänger. Die prorotype-chain ist intakt, d.h. solange man einer Kopie keine Werte direkt zuweist, sind sie sozusagen transparent, man sieht dann einfach die entsprechenden Eigenschaften der Vorgänger.

                                Für die Vererbung an weitere Instanzen ist kein Kontruktor notwendig, abgesehen natürlich von dem in object().

                                Als praktische Anwendung kann man sich z.B. DOM-Elemente vorstellen, die in Schritten dynamisch verändert werden, wobei man anschließend durch Löschen von neueren Werten in den Kopien die vorherigen Zustände ganz einfach wieder herstellen kann.

                                Natürlich können die Objekte auch jeweils durch weitere Eigenschaften/Methoden erweitert werden bevor oder während sie sich vererben (z.B. mit Hilfe meiner genannten oobject()-Funktion oder "zu Fuß"), usw. usf. Der Fantasie sind hier keine Grenzen gesetzt...

                                Ich wüsste jetzt gar nicht auf Anhieb, wie man das alles mit Konstruktoren machen würde, so vertraut ist mir inzwischen das object()-Konzept :-).

                                Gruß, Don P

                                --
                                sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
              2. Hi

                Das ist schon klar, das Problem ist aber wenn ich im Kontruktor Parameter brauche, was dann?

                Ihr redet aneinander vorbei!

                var obj = function(name) {

                this.name = name || 'default';
                }
                var newObj = object(obj);
                var newObj2 = object(obj);
                alert( newObj.name + '\n' + newObj2.name );

                  
                Nein, er sagt er kann in den meisten Fällen komplett auf Konstruktoren verzichten, und erhalte damit lesbareren Code.  
                  
                "Objects are mutable in JavaScript, so we can augment the new instances, giving them new fields and methods. These can then act as prototypes for even newer objects. We don't need classes to make lots of similar objects."  
                  
                Also:  
                  
                ~~~javascript
                  
                var object = function(o){function F(){};F.prototype=o;return new F();};  
                  
                /* Generation 1 */  
                var obj = {name: "Gen1"};  
                  
                /* Generation 2 */  
                var newObj = object(obj);  
                newObj.name="Gen2";  
                newObj.identify=function () { return this.name };  
                  
                /* Generation 3 */  
                var newObj2 = object(newObj);  
                newObj2.name="Gen3";  
                  
                  
                alert( obj.name + '\n' +newObj.identify() + '\n' + newObj2.identify() );  
                
                

                allerdings seine "Zeugungs"-Methode Object.prototype.begetObject ist keine kluge Idee! Jedes assoziative Array hat dann automatisch ein weiteres Element!

                  
                Object.prototype.begetObject = function () {  
                    function F() {}  
                    F.prototype = this;  
                    return new F();  
                };  
                  
                  
                hash={a:1,b:2};  
                  
                var out="";  
                for (i in hash) out+=i+':'+hash[i]+'\n';  
                alert(out)  
                
                

                Also Finger weg von Object.prototype!!!

                Lieber ein eigenes Wurzelobjekt definieren von dem alle "Spezialobjekte" abgeleitet werden.

                Hasta la vista
                  LanX

                1. Hi

                  Object.prototype.begetObject = function () {
                      function F() {}
                      F.prototype = this;
                      return new F();
                  };

                  hash={a:1,b:2};

                  var out="";
                  for (i in hash) out+=i+':'+hash[i]+'\n';
                  alert(out)

                  
                  >   
                  > Also Finger weg von Object.prototype!!!  
                  >   
                  > Lieber ein eigenes Wurzelobjekt definieren von dem alle "Spezialobjekte" abgeleitet werden.  
                    
                  ich habe ihn gerade angeschrieben dass er lieber Function.prototype.begetObject schreiben solle, um diese Probleme zu umgehen.  
                    
                  In JSLint propagiert er übrigens, dass man for (in) immer mit Vorsicht und im Zweifelsfalle mit hasOwnProperty nutzen solle, um solchen Problemen auszuweichen:  
                  ~~~javascript
                    
                  for (name in object) if (object.hasOwnProperty(name)) {  
                      ....  
                    
                  }
                  

                  http://www.jslint.com/lint.html

                  aber mit Function hat er dieses Problem hier zumindest nicht mehr!

                  Möge die Engine mit euch sein!
                    LanX

                  1. Hallo,

                    ich habe ihn gerade angeschrieben dass er lieber Function.prototype.begetObject schreiben solle, um diese Probleme zu umgehen.

                    Wen? Gott? Ach nee, wahrscheinlich den JavaScript-Halbgott Douglas Crockford ;-).

                    In JSLint propagiert er übrigens, dass man for (in) immer mit Vorsicht und im Zweifelsfalle mit hasOwnProperty nutzen solle, um solchen Problemen auszuweichen:

                    for (name in object) if (object.hasOwnProperty(name)) {
                        ....
                    }

                      
                    Ja, das ist natürlich die unausweichliche Konsequenz, wenn man Object erweitert. Das ist auch der Grund, warum ich hier nicht die Object.protoype.begetobject-Variante erwähnt habe, weil mir das ziemlich riskant scheint. In meinen eigenen Scripts mache ich das zwar manchmal, aber die sind auch nicht zum Verteilen da.  
                      
                    
                    > <http://www.jslint.com/lint.html>  
                    >   
                    > aber mit Function hat er dieses Problem hier zumindest nicht mehr!  
                      
                    Dass man eine function überhaupt erweitern kann, habe ich zum ersten mal hier bei Struppi gesehen. Wäre von selber nicht auf die Idee gekommen, das zu machen. Dachte immer Function ist Function, und Object ist Object. Sogar typeof unterscheidet sie ganz brav. Die Grenze scheint aber eher fließend zu sein oder gar nicht zu existieren...  
                      
                    Gruß, Don P  
                    
                    
                    1. Hallo Don

                      Na, wenns dich so überrascht, dann hab ich ne kleine Knobelaufagbe für dich:

                      jede "function" ist eine Instanz des Konstruktors "Function";
                      der Konstruktor "Function" erbt vom Konstruktor "Object";
                      "Object" ist (wie alle Konstruktoren) eine "function". (typeof Object)

                      viel Spass und schönes Wochenende
                       LanX

                      1. Hallo LanX,

                        Na, wenns dich so überrascht, dann hab ich ne kleine Knobelaufagbe für dich

                        Da gibt's nicht viel zu knobeln, ist doch völlig logisch. Dass mir etwas nicht bekannt ist, heißt ja nicht, dass ich es nicht verstehe, wenn es mir bekannt wird ;-) Danke jedenfalls für die Info.

                        Gruß, Don P

                    2. Hallo,

                      Dachte immer Function ist Function, und Object ist Object. Sogar typeof unterscheidet sie ganz brav. Die Grenze scheint aber eher fließend zu sein oder gar nicht zu existieren...

                      Alles ist eine Instanz von Object. Object ist der oberste Konstruktor aller JavaScript-Objekte (und dessen Prototyp der Prototyp aller Objekte).

                      Was die Unterscheidung von typeof angeht, so wird zwischen Objekten unterschieden, die die interne Methode [[Call]] kennen oder nicht, und das trifft auf Funktionsobjekte zu. (typeof gibt die internen Typen nicht ohne Nivellierung wieder und ist ist bloß zur Unterscheidung von Primitives und Objects interessant.)

                      Allerdings verstehe ich nicht, warum Function.prototype.begetObject jetzt alles besser macht. Der Sinn von Object.prototype ist ja, dass ich einfach objekt.begetObject() schreiben kann. Wozu allen Funktionsobjekten das anhängen? Dann kann ich doch nicht einfach { a : "b" }.begetObject() schreiben, was ja der Sinn der Sache war. Dann könnte ich die Methode auch ans globale Host-Objekt window oder an den Object-Konstruktor (nicht dessen prototype) kleben, weil ich sie ohnehin umformen muss, sodass sie das Objekt als Parameter enthält, anstatt dass sie über this darauf zugreifen kann.

                      Mathias

                      1. Hi

                        Allerdings verstehe ich nicht, warum Function.prototype.begetObject jetzt alles besser macht. Der Sinn von Object.prototype ist ja, dass ich einfach objekt.begetObject() schreiben kann. Wozu allen Funktionsobjekten das anhängen? Dann kann ich doch nicht einfach { a : "b" }.begetObject() schreiben, was ja der Sinn der Sache war.

                        Tatsächlich funktioniert es nur bei Kind-Objekten die bereits mit object() erzeugt wurden, weil die ja alle Konstruktoren sind ("return new F();").
                        Für die literalen Objekte klappt das nicht, die sind nur einfache Objekte.

                        oder man bräuchte eine literale schreibweise für Funktionen

                        Dann könnte ich die Methode auch ans globale Host-Objekt window

                        wo ist dann der Unterschied zu einer einfachen Funktion object()?

                        oder an den Object-Konstruktor (nicht dessen prototype) kleben, weil ich sie ohnehin umformen muss, sodass sie das Objekt als Parameter enthält, anstatt dass sie über this darauf zugreifen kann.

                        verstehe ich nicht kannst du mir dafür ein Beispiel zeiegn?

                        tschau
                         Kurt

                        1. Hi

                          Dann kann ich doch nicht einfach { a : "b" }.begetObject() schreiben, was ja der Sinn der Sache war.

                          ARGHH ... !!!!!!

                          sowas passiert wenn man direkt im Browser testet, und die Konstrukte des letzten Durchlaufs noch im Namensraum sind ...

                          Tatsächlich funktioniert es nur bei Kind-Objekten die bereits mit object() erzeugt wurden, weil die ja alle Konstruktoren sind ("return new F();").

                          Nein, tut's leider nicht. Habe mich aber auch verguckt.

                          Sowas obj= new F() erbt nicht von der Funktion F sondern vom prototyp von F. Der ist aber irgendwas, wenn er Literal definiert wurde nur ein Abkömmling von "Object" und nicht von "Function".

                          Irgendwo hat er auch recht, wenn er diese komische um die Ecke Vererberei kritisiert, das verwirrt ziemlich. Tja hab ihm schon ne zwote Mail geschickt ...

                          oder man bräuchte eine literale schreibweise für Funktionen

                          Du meinst fürs Funktionsobjekt, ja das würde funktionieren.

                          Man könnte auch ne Funktion nehmen die aus nem Literalobjekt {...} ein Funktionsobjekt macht:

                          ungefähr so:
                          toFunction (obj) {
                           F=function (){};
                           for (i in obj) { F[i]=obj[i] }
                           return F;
                          }

                          dann b0=toFunction({...});

                          oder halt eine eigene Objektklasse Begetter erschaffen.

                          b0=new Begetter({...});
                          b1=b0.beget(); usw...

                          aber dann kann man eigentlich auch gleich bei object() bleiben.

                          Dann könnte ich die Methode auch ans globale Host-Objekt window

                          wo ist dann der Unterschied zu einer einfachen Funktion object()?

                          oder an den Object-Konstruktor (nicht dessen prototype) kleben, weil ich sie ohnehin umformen muss, sodass sie das Objekt als Parameter enthält, anstatt dass sie über this darauf zugreifen kann.

                          verstehe ich nicht kannst du mir dafür ein Beispiel zeiegn?

                          Hmmm, ich denke er will die Funktion Object(){} , die der Konstruktor von Object ist, so überschreiben dass sie wie object() funktioniert, oder?

                          Das ist aber nicht ungefährlich wie die Diskussion von von Murphy/Kurt zeigt.

                          Möge die Engine mit euch sein!
                            LanX

                          1. ARGHH ... !!!!!!

                            UPS! :)

                          2. Hallo,

                            [...] Nein, tut's leider nicht. Habe mich aber auch verguckt.
                            ...
                            Irgendwo hat er auch recht, wenn er diese komische um die Ecke Vererberei kritisiert, das verwirrt ziemlich. Tja hab ihm schon ne zwote Mail geschickt ...

                            Tja, ich meine wirklich, du solltest es lieber lassen, den Mann zuzumüllen mit Mails wie "1. mach's doch lieber so und so... 2. äh nein, das war nichts, habe mich verguckt..." Wenn der etwas propagiert, dann hat er es sicher ausgiebig getestet und weiß, wovon er spricht. Oder denkst du im ernst, wenn es mit Function besser geklappt hätte, wäre ihm das entgangen?

                            Man könnte auch ne Funktion nehmen die aus nem Literalobjekt {...} ein Funktionsobjekt macht:

                            ungefähr so:
                            toFunction (obj) {
                            F=function (){};
                            for (i in obj) { F[i]=obj[i] }
                            return F;
                            }

                            Das ergibt doch kein "Funktionsobjekt", lediglich ein normales mit den Eigenschaften und Methoden des übergebenen Objekts.

                            Der Ansatz ist aber nicht schlecht, das habe ich hier doch schon vorgestellt mit meiner function oobject () {...}.

                            Wieso willst du Crockfords Lösung denn partout nicht akzeptieren oder immer eine noch bessere finden? Was stört dich denn daran? Dass man Object nicht unbedenklich erweitern sollte? Das wird doch auch gar nicht verlangt. Nicht ohne Grund steht wohl sein Vorschlag mit Object.prototype ganz am Ende des Artikels. Für standalone-Scripts, die nicht mit anderen zusammen eingebunden werden, ist das auch kein Problem. Man muss halt mit for..in aufpassen.

                            Hmmm, ich denke er will die Funktion Object(){} , die der Konstruktor von Object ist, so überschreiben dass sie wie object() funktioniert, oder?

                            Naja, er will einfach die ganze Konstruktor-Denke hinter sich lassen und eben nicht mit Hilfe von Klassen vererben, die durch Konstruktoren definiert sind. Denn ein Konstruktor kann immer nur eine Art Objekt erzeugen, wie im Konstruktor notiert. Das ist eine Einschränkung, die in einer Sprache mit prototypischer Vererbung einfach unnötig ist. Der eingebaute new-Operator lässt das Ganze aber leider so aussehen, als müsse man doch immer Klassen definieren. Mit object() entschärft bzw. umgeht man diese Einschränkung, das ist alles.

                            Gruß, Don P

                            1. Hallo,

                              Tja, ich meine wirklich, du solltest es lieber lassen, den Mann zuzumüllen

                              Mist, dabei bräuchte dein Halbgott doch dringend ne Penisverlängerung und ein Nigerianisches Millionenerbe! ;)

                              Man könnte auch ne Funktion nehmen die aus nem Literalobjekt {...} ein Funktionsobjekt macht:

                              ...

                              Das ergibt doch kein "Funktionsobjekt", lediglich ein normales mit den Eigenschaften und Methoden des übergebenen Objekts.

                                
                              a={a:1};  
                                
                              function toFunction (obj) {  
                                F=function (){};  
                                for (i in obj) { F[i]=obj[i] }  
                                return F;  
                              }  
                                
                              b=toFunction(a);  
                              alert(typeof(b)); //  'function'  
                              
                              

                              Der Ansatz ist aber nicht schlecht, das habe ich hier doch schon vorgestellt mit meiner function oobject () {...}.

                                
                              alert(typeof(oobject (a))); // 'object';  
                              
                              

                              Gut dass du den Unterschied zw. typeof und constructorof verstanden hast ... *fg*
                              https://forum.selfhtml.org/?t=168754&m=1102493

                              Wieso willst du Crockfords Lösung denn partout nicht akzeptieren oder immer eine noch bessere finden?

                              object() ist  IMHO  GENIAL!!! Besonders in Kombination mit nach außen gewendeten Konstruktoren (sog. "Makers" in den Kurt/Struppi Dialogen) !!!

                              Was man austesten sollte sind die Möglichkeiten des Kosntruktorchainings (sollte einfacher werden) und die Simulation von Mehrfachvererbung.

                              object.prototype aber ist höchstumstritten, da gibt es zwei sich krass gegenüberstehende Schulen, und er geht in dem Artikel überhaupt nicht auf die Problematik ein. Mein Verbesserungsvorschlag war zwar @%$&*... , aber sein Artikel ist dahingehend trotzdem Erklärungsbedürftig.

                              Insbesondere weil Scripte/Frameworks der anderen Schule dadurch Tabu werden.

                              Zumindest ein Link zu seiner Stilrichtlinie niemals for-in ohne if-Ratenschwanz zu nutzen wäre angebracht. JS-Lint kritisiert das per Default.

                              Wenn man das konsequent weiterdenkt müsste es auch Filterfunktionen wie own(), ownAttr(), inAttr(), ...usw oder analog vererbte Iteratoren (für Whileschleifen) geben.

                                
                              for (i in ownAttr(obj) {...}  
                              while (i in obj.ownAttr()) {...}  
                              
                              

                              und so weiter ...

                              Hmmm, ich denke er will die Funktion Object(){} , die der Konstruktor von Object ist, so überschreiben dass sie wie object() funktioniert, oder?

                              Naja, er will einfach die ganze Konstruktor-Denke hinter sich lassen und eben nicht mit Hilfe von Klassen vererben, die durch Konstruktoren definiert sind.

                              Das hat *Molily* gemeint???

                              So long!
                               LanX

                              1. Hallo,

                                Tja, ich meine wirklich, du solltest es lieber lassen, den Mann zuzumüllen

                                Mist, dabei bräuchte dein Halbgott doch dringend ne Penisverlängerung und ein Nigerianisches Millionenerbe! ;)

                                Klar, wer bräuchte das nicht... ;-)

                                b=toFunction(a);
                                alert(typeof(b)); //  'function'[/code]

                                Tatsächlich? Naja, das kommt davon, wenn man nicht jede noch so triviale Behauptung vorher testet, aber wem sage ich das...

                                Der Ansatz ist aber nicht schlecht, das habe ich hier doch schon vorgestellt mit meiner function oobject () {...}.

                                Gut dass du den Unterschied zw. typeof und constructorof verstanden hast ... *fg*
                                https://forum.selfhtml.org/?t=168754&m=1102493

                                Ich meinte hier nicht, dass mein oobject() ein Funktionsobjekt zurückgeben würde, sondern den Ansatz, die Eigenschaften/Methoden ggf. einzeln zuzuweisen.

                                object() ist  IMHO  GENIAL!!! Besonders in Kombination mit nach außen gewendeten Konstruktoren (sog. "Makers" in den Kurt/Struppi Dialogen) !!!

                                Dan sind wir uns ja einig.

                                Was man austesten sollte sind die Möglichkeiten des Kosntruktorchainings (sollte einfacher werden) und die Simulation von Mehrfachvererbung.

                                So weit bin ich noch nicht vorgedrungen. Was meinst du denn mit Kosntruktorchaining und Mehrfachvererbung?

                                object.prototype aber ist höchstumstritten, da gibt es zwei sich krass gegenüberstehende Schulen, und er geht in dem Artikel überhaupt nicht auf die Problematik ein. Mein Verbesserungsvorschlag war zwar @%$&*... , aber sein Artikel ist dahingehend trotzdem Erklärungsbedürftig.

                                Du meinst wohl Object.prototype. Dass das umstritten ist, liegt auf der Hand. Ich glaube auch nicht, dass man da zufridenstellende endgültige Aussagen machen kann. Das hält jeder nach seinem Gusto. Mir scheint das nicht wirklich eine Diskussion wert, die darüber hinaus ginge, dass man die möglichen Nachteile erwähnt.

                                Insbesondere weil Scripte/Frameworks der anderen Schule dadurch Tabu werden.

                                Eben. Ein Rattenschwanz ohne Ende.

                                Das hat *Molily* gemeint???

                                molily? Das kommt davon, wenn du immer nur von "er" schreibst. Hellsehen is hier halt nich...

                                Gruß, Don P

                                --
                                sh:( fo:) ch:? rl:( br:] n4:~ ie:% mo:? va:{ js:) de:/ zu:] fl:( ss:| ls:&
                              2. Hi LanX!

                                object.prototype aber ist höchstumstritten, da gibt es zwei sich krass gegenüberstehende Schulen, und er geht in dem Artikel überhaupt nicht auf die Problematik ein. Mein Verbesserungsvorschlag war zwar @%$&*... , aber sein Artikel ist dahingehend trotzdem Erklärungsbedürftig.

                                ganz deiner Meinung, schau mal hier https://forum.selfhtml.org/?t=169127&m=1104127

                                Wenn man das konsequent weiterdenkt müsste es auch Filterfunktionen wie own(), ownAttr(), inAttr(), ...usw oder analog vererbte Iteratoren (für Whileschleifen) geben.

                                for (i in ownAttr(obj) {...}
                                while (i in obj.ownAttr()) {...}

                                
                                >   
                                > und so weiter ...  
                                  
                                hmm , mit dem for (i in ownAttr(obj)  fällst du aber IMHO leider wieder auf die Schnau ... ähm du drehst dich im Kreis :)  
                                  
                                Du kannst hier nur ein Objekt zurückgeben, dass von Object() erbt ... BUMM.  
                                for in ohne hasOwnAttribute geht halt nicht.  
                                  
                                die Idee mit dem Iterator ist aber machbar, AFAIS hat prototype.js genau so seinen Konstruktor Hash realisiert: <http://prototypejs.org/api/hash#method-each>  
                                  
                                Die hatten scheints auch selbst ziemliche Probleme mit Hash (siehe deprecated Hinweise) udn bieten Alternativ noch die Möglichkeit sich Arrays() der values udn keys zurückgeben zu lassen.  
                                  
                                for-in ohne Vererbung geht halt leider nicht!  
                                  
                                Grüße  
                                 Kurt
                                
                                1. Hi

                                  hmm , mit dem for (i in ownAttr(obj)  fällst du aber IMHO leider wieder auf die Schnau ... ähm du drehst dich im Kreis :)

                                  hmm hast recht ... hoffentlich tut sich da was in der nächsten Version von JS!

                                  die Idee mit dem Iterator ist aber machbar, AFAIS hat prototype.js genau so seinen Konstruktor Hash realisiert: http://prototypejs.org/api/hash#method-each

                                  ja schau mal in "deinem" anderen Thread! :)

                                  https://forum.selfhtml.org/?t=169127&m=1104317

                                  Und ärger nicht die Mods!

                                  Tschau
                                   LanX

                      2. Hallo,

                        Alles ist eine Instanz von Object. Object ist der oberste Konstruktor aller JavaScript-Objekte (und dessen Prototyp der Prototyp aller Objekte).

                        Ah ja, danke. Jetzt ist es noch klarer.

                        Was die Unterscheidung von typeof angeht, so wird zwischen Objekten unterschieden, die die interne Methode [[Call]] kennen oder nicht, und das trifft auf Funktionsobjekte zu. (typeof gibt die internen Typen nicht ohne Nivellierung wieder und ist ist bloß zur Unterscheidung von Primitives und Objects interessant.)

                        Die Call-Methode macht also den Unterschied, das leuchtet ein.

                        Gruß, Don P

        2. Threaddrift von http://board.perl-community.de/thread/11513/startWithMessage=36

          Murphy schrieb:

          Nachtrag zum Klonen von Objekten: Auch wenn der ECMA-262 Standard das nicht zwingend vorschreibt, habe ich festgestellt, dass sowohl SpiderMonkey (JavaScript-Engine von Firefox und Co) als auch JavaScriptCore (JavaScript-Engine von Konqueror, Safari und Co) das folgende Idiom zum Klonen eines Objektes unterstützen:

            
          
          > var clone = new Object(original);  
          
          

          Dieser Aufruf hat fast denselben Effekt wie die weiter oben vorgeschlagene clone-Methode. Der Unterschied ist, dass er für die statischen eingebauten Objekte (wie Object) keinen Klon anfertigt, sondern das Objekt selbst wieder zurückgibt und ferner dass er auch mit Eingabewerten klar kommt, die Arrays, Strings, Zahlen, null oder undef sind. Eigentlich ein sehr sinnvolles Verhalten :-)

          Hi Murphy,

          ganz kann ichs doch nicht nachvollziehen, bei mir liefert y=new Object(x) immer einen Alias auf x statt eines Kindes,

            
          k1=function (){this.iname="1"};  
          k1.prototype={kname:"k1"};  
          k2= new Object(k1);  
            
          i1=new k1();  
          i2=new Object(i1);  
            
          alert(k1 == k2 ); //=true  
          alert(i1 == i2 )  //=true  
          
          

          vielleicht hab ich auch etwas falsch verstanden.

          Ciao
           Kurt

          1. Ich habe auf den Webseiten von Mozilla (http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object) das hier gelesen:
            "[...] The Object constructor creates an object wrapper for the given value. If the value is null or undefined, it will create and return an empty object, otherwise, it will return an object of type that corresponds to the given value. [...]"

            Ich dachte, dass das sehr nach einer Klonierungsfunktion klingt und habe es "erfolgreich" ausprobiert. Jetzt muss ich allerdings feststellen, dass es gar nicht so funktioniert, wie ich dachte, sondern so, wie Du geschrieben hast...

            Wahrscheinlich war's gestern schon zu spät und die stundenlange Programmiererei von thermodynamischen Zustandsfunktionen vorher hat mein Gehirn überhitzt oder so ;-)

            1. Ah, schön du bist hier angekommen. :)

              eine  Frage noch, wenn Crockford sagt, JS hätte die Prototypische Vererbung
              vermurkst um wie eine Klassenbasierte auszusehen [1].

              "In a prototypal system, objects inherit from objects. JavaScript, however, lacks an operator that performs that operation. Instead it has a new operator, such that
              new f() produces a new object that inherits from f.prototype
              This indirection was intended to make the language seem more familiar to classically trained programmers, "

              A Prototypal system? Ich kann im Netz keine anderen Repräsentaten prototypischer Vererbung finden, deren Vorgabe hätten vermurkst werden können.

              Gibts eine Norm was "echte" prototypische Vererbung sein könnte?

              Ist damit Self gemeint? http://de.wikipedia.org/wiki/Self_(Programmiersprache)

              Verstehe ich das richtig, dass "echte" prototypische Sprachen im Gegensatz zu JS kein "new" haben um aus Konstruktoren Instanzen abzuleiten und deswegen keine zwei Formen von Objekten existieren?

              Bye Kurt

              [1] sag ich doch! ;-)

              1. Hallo,

                eine  Frage noch, wenn Crockford sagt, JS hätte die Prototypische Vererbung vermurkst um wie eine Klassenbasierte auszusehen.

                Leider ist mir auch mir keine andere prototypische Sprache bekannt, aber Crockfords Ausführungen nach ist es klar so, dass JavaScript tatsächlich ein "prototypal system" ist [1].

                "Vermurkst" ist es lediglich in dem Sinne, dass man es seiner Meinung nach versäumt hat, einen Operator einzuführen, der ein Objekt direkt von einem anderen erben lässt: "In a prototypal system, objects inherit from objects."

                Er beklagt, dass die Vererbung mit dem new-Operator nur indirekt über den Prototyp eines anderen Objekts geschieht: "it [javascript] has a new operator, such that new f() produces a new object that inherits from f.prototype"

                Es wäre ihm aber lieber gewesen und entspräche dann seiner Vorstellung einer echten prototypischen Spache, wenn der Operator, nennen wir ihn mal "neuu" (n-e-dabbeljuu), mit neuu f() ein Objekt lieferte, das direkt von f erbt, anstatt von f.prototype.

                Der Unterschied ist der, dass man z.B. mit neuu {prop: val} ein leeres Objekt erhalten könnte, das {prop: val} zum Prototyp hat (man könnte über prop auf val zugreifen), während new {prop: val} ein leeres Objekt ergeben würde, das Object zum Prototyp hätte (also ={}), so dass prop und val dann vollends verloren wären, weshalb das auch realiter zum Fehler "is not a constructor" führt. Man ist somit quasi gezwungen, Konstruktoren zu benutzen: "This indirection was intended to make the language seem more familiar to classically trained programmers".

                Man denke sich also nur noch einen solchen Operator neuu dazu - und fertig ist das "true prototypal system", das Doug vorschwebt.

                Nichts leichter als das, führt er dann weiter aus ("Fortunately, it is easy to create an operator that implements true prototypal inheritance"), und präsentiert seine m.E. geniale object-Funktion:

                  
                    function object(o) {  
                        function F() {}  
                        F.prototype = o;  
                        return new F();  
                    }
                

                Natürlich ist es eine Funktion, kein Operator. Aber sie leistet genau das, was er verlangt: Das erzeugte Objekt hat im Prototyp die Eigenschaften und Methoden des Ausgangsobjekts, nicht lediglich die des Prototyps vom Ausgangsobjekt. Ansonsten hat es erst mal keine eigenen Eigenschaften und Methoden. Letzteres mag auf den ersten Blick verwirren, stellt sich aber als äußerst nützlich heraus, wenn man ein Weilchen damit experimentiert...

                [1] "JavaScript's constructor pattern [...] obscured JavaScript's true prototypal nature." (to obscure = verschleiern, verbergen) - ohne Gewähr ;)

                Gruß, Don P

              2. A Prototypal system? Ich kann im Netz keine anderen Repräsentaten prototypischer Vererbung finden, deren Vorgabe hätten vermurkst werden können.

                Gibts eine Norm was "echte" prototypische Vererbung sein könnte?

                Ist damit Self gemeint? http://de.wikipedia.org/wiki/Self_(Programmiersprache)

                Naja, außer Self gibt es noch ein paar andere Sprachen, die recht puristisch die prototypische Vererbung verfolgen. Zum Beispiel Io http://iolanguage.com/ und, soweit ich weiß, Lisaac http://isaacproject.u-strasbg.fr/li.html. Aber verbreitet sind prototypenbasierte Sprachen eigentlich nicht. Das Konzept ist wohl gerade nicht in Mode :-)

                Verstehe ich das richtig, dass "echte" prototypische Sprachen im Gegensatz zu JS kein "new" haben um aus Konstruktoren Instanzen abzuleiten und deswegen keine zwei Formen von Objekten existieren?

                Crockford wohl, dass eine prototypenbasierte Sprache außer einer Klonierungsoperation keinen weiteren Schnickschnack benötigt um Vererbung zu unterstützen.

                Es existiert auch bei JavaScript streng genommen nur eine Form von Objekt. Ok, die Werte undefined und null sind etwas besonderes, weil sie eigentlich keine Objekte sind. Booleans, Zahlen und Strings können zwar als Objekte agieren, werden aber gelegentlich auch in primitiverer Maschinenrepräsentation herumübergeben, wobei dann benutzerdefinierte Eigenschaften nicht mitgenommen werden (z.B.: var n = new Number(42); n.foo = "bar"; alert(n.foo); n = n + 0; alert(n.foo);). Und manchmal nehmen auch andere Objekte eine Sonderstellung in der Implementation der Skriptengines ein. Aber im Prinzip sind alle Objekte gleichwertig.

                Bei JavaScriptCore zum Beispiel macht selbst die C-API keinen Unterschied zwischen Funktionen / Konstruktoren, Arrays oder anderen Objekten.

                1. Hi

                  Es existiert auch bei JavaScript streng genommen nur eine Form von Objekt.

                  naja

                  typeof(KONSTRUKTOR) == "function"
                  typeof(INSTANZ)     == "object"

                  und wenn du sowas abfragst

                  INSTANZ1 instanceof INSTANZ2

                  bekommst du ne Fehlermeldung
                  "INSTANZ2 is not a constructor"

                  bye
                   Kurt

                2. Hallo,

                  Booleans, Zahlen und Strings können zwar als Objekte agieren, werden aber gelegentlich auch in primitiverer Maschinenrepräsentation herumübergeben, wobei dann benutzerdefinierte Eigenschaften nicht mitgenommen werden (z.B.: var n = new Number(42); n.foo = "bar"; alert(n.foo); n = n + 0; alert(n.foo);).

                  Das Beispiel führt eine Umwandlung in Primitive durch, das liegt am +-Operator, der natürlich nicht mit Objects rechnen kann. Das alte Object wird hier einfach verworfen, nachdem keine Referenz darauf mehr besteht. n ist nach der Zuweisung ein Primitive, ein völlig neues, daher hat es auch keine foo-Eigenschaft.

                  Mathias

  2. Hi

    Wieso ist die Reihenfolge relevant??? Prototyp wird doch dynamisch ausgewertet...

    Zugegeben verwirrend ... mal ganz grob wie ich es sehe:

    Es stimmt Prototype (oder besser die Prototypes) sind Unter-Objekte eines Objekts, die erst zur Laufzeit zusätzlich durchsucht werden. Du kannst ihnen am Konstruktor einzelne Attribute oder Methoden auch nach der Instanzierung noch zuweisen und die Instanzen sehen sie sofort.

    Aber jedes erbende Object hat zusätzlich noch den internen(!) "Prototype chain" im Attribut "__proto__" wo die vererbenden (also dynamisch zu durchsuchenden) Prototypes referenziert werden. Veränderungen geschehen immer statisch beim Zuweisen eines vererbenden Objekts auf ".prototype" wobei in diesem Moment die Refrenzkette des Prototypechain des erblassenden "__proto__" am erbenden "__proto__" angehängt wird.

    Kann mir jemand bitte einen guten Link geben wo Vererbungsketten und prototype genau erklärt werden?

    http://www.cs.rit.edu/~atk/JavaScript/manuals/jsobj/index.htm#1040208

    alt aber fundamental. Ansonsten gibst noch ein ziemlich gutes O'reilly Buch zum Thema JS.

    Tschau LanX

  3. Hallo,

    wenn man Vererbungsketten konstruktor1.prototype = new konstruktor2 erzeugt, dann muss das wohl immer von oben nach unten erfolgen. Wirklich plausibel scheint mir das nicht und ich wüsste auch nicht, wo das explizit festgelegt ist.

    Wie gesagt, das nachträgliche Erweitern geht ja und das diese Member werden auch korrekt vererbt. Aber wenn ich den Prototyp überschreibe, so hat das nur Auswirkung auf später erzeugte Instanzen.

    function Tier () {}  
      
    var tier_instanz = new Tier;  
    Tier.prototype = { lebewesen : true };  
      
    alert(tier_instanz.lebewesen);  
      
    var tier_instanz2 = new Tier;  
    alert(tier_instanz2.lebewesen);
    

    Das scheint mir das Grundproblem zu sein. Hat mir mehrfacher Vererbung direkt nichts zu tun. Tier.prototype.lebewesen = true würde wie gesagt funktionieren.

    Mathias

  4. Hi

    wenn du NEW in JS anwendest, ist einer der Schritte den prototype des Constructors im "__proto__" Attribut der Instance zu verlinken:

      
    INSTANCE= new CONSTRUCTOR();  
    ; => INSTANCE["__proto__"]=CONSTRUCTOR.prototype;  
    
    

    Vererbung funtioniert dann durch ein schrittweises durchsuchen der
    "Prototype-Chain" in den "__proto__" attributen.

    also in Pseudocode linear programmiert:

      
    function getAttr(Attr,ThisObj) {  
    // ? local (this) vorhanden ???  
       Obj=ThisObj;  
       if (Obj.Attr)  
          {return Obj.Attr};  
    // ? im Prototype des Elter CONSTRUCTOR vorhanden ???  
       Obj=ThisObj["__proto__"];  
       if (Obj.Attr)  
           {return Obj.Attr};  
    // ? im Prototype des Großelter vorhanden ??  
       Obj=ThisObj["__proto__"]["__proto__"];  
    // identisch mit CONSTRUCTOR.prototype["__proto__"]  
       if (Obj.Attr)  
           {return Obj.Attr};  
    // ... usw bis es kein Eltern"__Proto__" mehr gibt  
    }  
    
    

    man hangelt sich also durch die prototype Attribute der "Konstruktoren" die die üblichen "Klassendefinition" ersetzen, ähnlich ISA in Perl.

    deswegen schreibt man auch zwecks Vererbung von SUPER zu SUB
    SUB.prototype=new SUPER;
    womit implizit
    SUB.prototype.__proto__=SUPER.prototype

    ACHTUNG: SUB.__proto__ wird nicht geändert, es ist sein Prototype Unterobjekt welches Instance des vererbenden SUPER-Konstruktors wird.

    OK, soweit der Mechanismus nun zu deinem Casus cnacktus:

    class1.prototype = new class0();
    instance.prototype = new class1();

    =>
    class1.prototype.__proto__=class0.prototype;
    instance.prototype.__proto__=class1.prototype;

    funktioniert!

    instance.prototype = new class1();

    => instance.prototype.__proto__=class1.prototype;

    class1.prototype = new class0();

    class1.prototype.__proto__=class0.prototype;

    MOMENT hier hast du class1.prototype neu von class0 instanziert und mit einem neuen Objekt überschrieben! instance.prototype.__proto__ verweist aber noch auf das alte Objekt.

    Ich bin zugegeben selbst verwirrt ... leider weiß ich auch gerade nicht wie man in JS eine explizite Objekt_ID eines Objektes abfragt um das Verhalten zu überprüfen. ... habe jetzt auch keine anderen Browser da.

    Bye
     LanX

    1. Nachtrag...

      MOMENT hier hast du class1.prototype neu von class0 instanziert und mit einem neuen Objekt überschrieben! instance.prototype.__proto__ verweist aber noch auf das alte Objekt.

      genau und das ist der Punkt, stell dir die Prototyp-unterobjekte wie Perlhashes als Objektattribute vor. Die Hashes sind untereinander über "__proto__" verlinkt.

      Wenn du nachträglich SUB.prototype.attr="ATTR" schreibst veränderst du ein vorhandenes Hash, beim späteren  durchsuchen der Linkliste wird das während der Laufzeit von INSTANCE gefunden.

      Schreibst du aber SUB.prototype=new SUPER(); erzeugst du ein ganz neues Hash das aber jetzt nicht von einem Erben verlinkt ist. Das alte Hash bleibt auch im Speicher existent solange es verlinkt bleibt (keine Garbage Collection) und wird ganz normal durchsucht und kann natürlcih nicht die eigenschaften des neuen Hashes wiederspiegeln!!!

      Im Perlobjektmodell würde dieses Verhalten einem dynamischen ändern des ISA-Arrays und damit der Erbfolge entsprechen.

      1. Hi

        Danke LanX deine Erklärung hat mir seeehr geholfen! :)

        eine Anmerkung noch...

        Im Perlobjektmodell würde dieses Verhalten einem dynamischen ändern des ISA-Arrays und damit der Erbfolge entsprechen.

        das dürfte nicht so einfach sein, ISA hält IMHO die "Namen" der zu beerbenden Oberklassen und nicht wie du so schön dargestellt hast eine Referenz auf den zu erbenden Prototype einer Oberklasse. D.H die Reihefolge der Erbbeziehungen wären Schnuppe.

        aber danke, ich denke in beiden Sprachen sollte man von solchen Manipulationen Abstand nehmen :)

        Grüße
         Kurt

    2. Hallo,

      hier hast du class1.prototype neu von class0 instanziert und mit einem neuen Objekt überschrieben! instance.prototype.__proto__ verweist aber noch auf das alte Objekt.

      Das stimmt.

      Übrigens ist __proto__ eine Mozilla-proprietäre Sache, die es in ECMAScript und anderen Browsern nicht gibt. Sie spiegelt aber die interne ECMAScript-Eigenschaft [[Prototype]] wieder, soweit ich weiß, insofern ist der Hinweis sehr nützlich.

      Dre Knackpunkt ist aber, WANN diese Eigenschaft gesetzt wird. Sie wird nämlich nur einmal gesetzt, und zwar in dem Moment, in dem die Instanz mit new erzeugt wird. Der new-Operator ruft [[Construct]] auf: http://bclary.com/log/2004/11/07/#a-13.2.2
      Darin wird die [[Prototype]]-Eigenschaft der Instanz auf das gegenwärtige prototype-Objekt des Konstruktors gesetzt (referenziert, wie du sagst).

      Die Ursache ist also nichts anderes, als auch dieses Beispiel illustriert:

      prot1 = {}  
      ref = prot1;  
      prot2 = {};
      

      Jetzt ist ref natürlich noch prot1. Und das Objekt formally known as prot1 wird nicht vom Garbage Collector abgeräumt, weil noch eine Variable darauf verweist.

      leider weiß ich auch gerade nicht wie man in JS eine explizite Objekt_ID eines Objektes abfragt um das Verhalten zu überprüfen.

      Man kann die Identität von Objekten mit == bzw. === prüfen.

      function Konstruktor () {}  
        
      var instanz1 = new Konstruktor;  
      Konstruktor.prototype = {  
       neueEigenschaft : true  
      };  
      var instanz2 = new Konstruktor;  
        
      alert(instanz1.constructor + "\n" + instanz2.constructor);  
      alert(instanz1.constructor === instanz2.constructor);  
      alert(instanz1.constructor.prototype === instanz2.constructor.prototype);  
      alert(Konstruktor.prototype.isPrototypeOf(instanz1) + " " + Konstruktor.prototype.isPrototypeOf(instanz2));  
      alert(instanz1.__proto__ === instanz2.__proto__);  
      alert(instanz1.neueEigenschaft + "\n" + instanz2.neueEigenschaft);
      

      Offenbar wird mit der Zuweisung an prototype auch die constructor-Eigenschaft überschrieben. Logisch, dann stimmt der Prototyp auch nicht mehr überein. Was ist denn, wenn wir die constructor-Eigenschaft wieder explizit setzen?

      Konstruktor.prototype = {  
       neueEigenschaft : true,  
       constructor : Konstruktor  
      };
      

      Dann stimmen zwar die constructor-Eigenschaften von instanz1 und isntanz2 überein und folglich dessen prototype-Eigenschaft. Aber neueEigenschaft gibts immer noch nur bei instanz2. Denn die __proto__- bzw. [[Prototype]]-Eigenschaften unterscheiden sich noch. instanz1.__proto__ ist ein leeres Object, instanz2.__proto__ hat logischerweise zwei Member. Dementsprechend ist Konstruktor.prototype.isPrototypeOf(instanz1) false.

      Mathias

  5. Hi

    Die OO-features unterscheiden sich ja auch mit den JS-versionen , z.B apply udn call.

    Die Version kann man im Script-tag einstellen....

    folgende Fragen:
    a) welche bekomme ich z.B. im Mozilla wenn ich keine angebe? 1.0?
    b) welche kann man gefahrlos angeben, sodass sie in allen Browsern ab V6 (5?) funktioniert?
    c) welche entsprechen dem (den?) ECMA-Standard(s)?

    Grüße
     Kurt

    1. OK wenn ich selfhtml richtig deute und davon ausgehe dass die Infos aktuell sind dann sollte man auf eine Versionsnummer verzichten und lieber bei die gewünschten Feature abtesten.

      http://de.selfhtml.org/javascript/intro.htm#standards_varianten_versionen

      Es gibt aber Versionsunterschiede was "altebekannte" Methoden zurückgeben, rsikiere ich jetzt bei angabe von z.B. 1.3 das der eine Browser es nicht ausführt und das der andere Browser DOM-Features "vergisst" der eigentlich hatte?

      verwirrt
        Kurt

      1. Hallo,

        vergiss »JavaScript-Versionen« und schreibe ECMAScript. Das verstehen alle aktuellen Browser grundlegend. Einzelne Features kannst du i.d.R. wie auch sonst immer durch Objektabfragen in Erfahrung bringen. Ausnahmen gibts natürlich, wo sich die Grammatik geändert hat. Die betreffen aber aus heutiger Sicht vorsintflutliche Browser.
        Aber das habe ich ja auch im Artikel geschrieben, den du gefunden hast.

        Es gibt aber Versionsunterschiede was "altebekannte" Methoden zurückgeben

        Was meinst du damit?

        rsikiere ich jetzt bei angabe von z.B. 1.3 das der eine Browser es nicht ausführt

        Wenn du language="javascript1.3" angibst, führen den Code nur Browser aus, die von sich behaupten, Netscape JavaScript 1.3 zu implementieren. Das ist der Sinn der Angabe.

        und das der andere Browser DOM-Features "vergisst" der eigentlich hatte?

        Nein, das auf keinen Fall. Egal, welches language-Attribut du setzt, das Script hat immer Zugriff auf alle Fähigkeiten der Engine und das Script wird immer mit ein und derselben Engine verarbeitet.

        Mathias

        1. Aber das habe ich ja auch im Artikel geschrieben, den du gefunden hast.

          Ups, den verlinkten Absatz aus der SELFHTML-Doku habe ich zwar auch redigiert, aber ich meinte den hier:
          http://aktuell.de.selfhtml.org/weblog/javascript-standards

          Mathias

    2. Hallo,

      a) welche bekomme ich z.B. im Mozilla wenn ich keine angebe? 1.0?

      Die neueste, das ist im Gecko 1.7 bzw. bei Beta-Versionen 1.8 (1.6 bis 1.8 sind proprietäre Mozilla-Erfindungen - das offizielle Netscape JavaScript gibts nur bis 1.5).

      b) welche kann man gefahrlos angeben, sodass sie in allen Browsern ab V6 (5?) funktioniert?

      Die Frage ist unsinnig.

      Was ist eine »Version 5«? Die gibts nur im IE. Dem JScript-Stand des IE 5.x entsprechen bei anderen Browsern andere Versionen.
      Die JScript-Engine im IE 5.x hat grobe Abweichungen vom ECMAScript-Standard. Die Konformität wurde in den Folgeversionen verbessern, aber Unterschiede bestehen immer noch.

      c) welche entsprechen dem (den?) ECMA-Standard(s)?

      JavaScript 1.5 ist eine konforme Implementierung von ECMAScript Edition 3. (1.6 bis 1.8 auch, allerdings haben die Zusätze im Sprachkern, die es im ECMAScript-Standard nicht gibt.)

      Mathias

      1. Hi

        b) welche kann man gefahrlos angeben, sodass sie in allen Browsern ab V6 (5?) funktioniert?

        Die Frage ist unsinnig.

        Ist diese Antwort sinnig?

        Was ist eine »Version 5«? Die gibts nur im IE.

        eben!

        Dem JScript-Stand des IE 5.x entsprechen bei anderen Browsern andere Versionen.
        Die JScript-Engine im IE 5.x hat grobe Abweichungen vom ECMAScript-Standard. Die Konformität wurde in den Folgeversionen verbessern, aber Unterschiede bestehen immer noch.

        c) welche entsprechen dem (den?) ECMA-Standard(s)?
        JavaScript 1.5 ist eine konforme Implementierung von ECMAScript Edition 3. (1.6 bis 1.8 auch, allerdings haben die Zusätze im Sprachkern, die es im ECMAScript-Standard nicht gibt.)

        die ECMA-Doku ist nur theoretisch brauchbar ... wenn ich dich und deine Artikel recht verstehe sollte man sich an die Netscape 1.3 Doku orientieren, aber die 1.5er wg ECMA vergleichen. Die Schnittmenge ist OK, bei Diffs könnte es Probleme geben.

        Desweiteren keine Versionsnummer voraussetzen und ordentlich testen.
        Wenn was wichtiges fehlt muss man mit Existenzweichen ausbessern.

        Danke damit kann ich leben!
          Kurt

        1. Hallo,

          wenn ich dich und deine Artikel recht verstehe sollte man sich an die Netscape 1.3 Doku orientieren, aber die 1.5er wg ECMA vergleichen.

          Brauchbar ist diese hier:
          http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference

          Betrifft natürlich nur den Core. JS 1.3 ist mehr. Da kommt halt noch das W3C DOM hinzu:

          http://www.w3.org/TR/DOM-Level-3-Core/core.html
          http://www.w3.org/TR/DOM-Level-2-HTML/html.html

          Wobei eben nicht alles standardisiert ist. Da muss man in die Herstellereigenen Dokus schauen:

          http://developer.mozilla.org/en/docs/Gecko_DOM_Reference
          http://msdn2.microsoft.com/en-us/library/ms533050.aspx

          Bzw. eben einfach Dokus wie SELFHTML oder Quirksmode.

          Mathias

          1. Hi

            wenn ich dich und deine Artikel recht verstehe sollte man sich an die Netscape 1.3 Doku orientieren, aber die 1.5er wg ECMA vergleichen.

            Brauchbar ist diese hier:
            ...

            Danke, gebookmarkt! :)

            Tschau
             Kurt

  6. Hi

    ich habe in kaum einem Thread hier so viel gelernt wie in diesem, ich möchte mich bei allen Beteiligten nochmal bedanken!

    Bye
      Kurt

    1. ich habe in kaum einem Thread hier so viel gelernt wie in diesem, ich möchte mich bei allen Beteiligten nochmal bedanken!

      dito.

      War auch für mich sehr lehrreich, wie die meisten deiner "Erbsenzähler" Threads ;-)

      Struppi.