Hansi: An die Experten

Hallo

Wieso funktioniert das nicht???:

  
function makeClass(proto){  
  var f = proto.init;  
  f.protoype = proto;  
  return f;  
}  
Person = makeClass({  
  init:function(name){  
    this.name = name  
  },  
  alert:function(){  
    alert(name)  
  }  
})  
Joe = new Person(4);  
Joe.alert();  

Es kommt die Fehlermeldung
Uncaught TypeError: Object [object Object] has no method 'alert'

  1. Uuups sorry, es funktioniert, hatte nur ein Schreibfehler.

    function makeClass(proto){  
      var f = proto.init;  
      f.prototype = proto;  
      return f;  
    }  
    Person = makeClass({  
      init:function(name){  
        this.name = name  
      },  
      alert:function(){  
        alert(this.name)  
      }  
    })  
    Joe = new Person(4);  
    Joe.alert();
    

    function makeClass(proto){
      var f = proto.init;
      f.protoype = proto;
      return f;
    }
    Person = makeClass({
      init:function(name){
        this.name = name
      },
      alert:function(){
        alert(name)
      }
    })
    Joe = new Person(4);
    Joe.alert();

    
    >   
    > Es kommt die Fehlermeldung  
    > Uncaught TypeError: Object [object Object] has no method 'alert'
    
    1. Uuups sorry, es funktioniert, hatte nur ein Schreibfehler.

      So kann man sich irren. Ist mir auch nicht aufgefallen.

      Struppi.

    2. function makeClass(proto){

      var f = proto.init;
        f.prototype = proto;
        return f;
      }
      Person = makeClass({
        init:function(name){
          this.name = name
        },
        alert:function(){
          alert(this.name)
        }
      })
      Joe = new Person(4);
      Joe.alert();

        
      Interessant, wie man mit etwas Meta-Code die Funktionsweise von JavaScript verdunkeln kann. Aus Interesse: Wozu braucht man diese Helferfunktion? Ist es unverständlicher oder mehr Schreibarbeit, Konstruktoren und Prototypen ganz konventionell zu notieren:  
        
      ~~~javascript
      function Person (name) {  
         this.name = name;  
      }  
      Person.prototype = {  
         alert : function () {  
            alert(this.name);  
         }  
      };  
      var joe = new Person('Joe');  
      joe.alert();
      

      Ich find es eher verwirrend, dass die init-Methode gleichzeitig der Konstruktor ist, an dem dann auch das prototypische Objekt hängt. Das widerspricht dem Verhalten von sämtlichen Umsetzungen von »Pseudoklassen« (aus Mootools, Prototype usw.). Also wenn ich Pseudoklassen will, dann würde ich eher eine dieser verwenden. Eine Helferfunktion »makeClass« zu nennen, die lediglich eine kompaktere Schreibweise des Konstruktors als Eintrag eines Object-Literals erlaubt, vereinfacht die Sache m.M.n. nicht.

      Instanzen können nur über »init« auf ihren Konstruktor zugreifen - was nicht über das standardmäßige »constructor« möglich ist, weil der Prototyp hier komplett überschrieben wird. Das finde ich ebenfalls verwirrend.

      Mathias

      1. Hallo Mathias

        Danke für deine Inputs!
        Mir geht es eigentlich nur darum mit Javascript zu experimentieren um es besser zu verstehen.
        Und ja, in einem zweiten Schritt möchte einen guten weg finden, ohne den Overhead von Mootools und co., weniger schreib-intensive, übersichtliche und doch noch performante, "classen/prototypen" zu schreiben.

        Vieleicht hast du noch weitere Ideen?

        Gruss Hansi

        1. Und ja, in einem zweiten Schritt möchte einen guten weg finden, ohne den Overhead von Mootools und co., weniger schreib-intensive, übersichtliche und doch noch performante, "classen/prototypen" zu schreiben.

          Performant ist eigentlich nur der Standard JS Weg. Alles andere geht Umwege, weil die Vererbung in JS etwas komplizierter ist und es keine vorgefertigten Funktionen gibt, um z.b. auf SUPER Funktionen zu zugreifen.

          Das wird z.b. bei Mootools umgesetzt, zum Preis, dass das erzeugen von eigenen Objekten um den Faktor zehn langsamer ist.

          Vieleicht hast du noch weitere Ideen?

          Dein Weg, bringt erstmal gar nichts, wie molily schon schrieb, ist es einfach nur ein etwas verquerer Weg, ein eignes Objekt zu erzeugen. Das ganze erinnert leicht an den Ansatz von Crockford, mit dem es möglich ist eine Vererbung in JS umzusetzen, die nicht den Konstruktor des parent Objekt aufruft.

          Mein aktueller Ansatz, der eine Mischung aus diversen Frameworks ist, sieht so aus:

          Function.prototype.Extend = function(b) {  
              var o = this;  
              var proto = b.prototype || b;  
            
              function Chain() {}  
              Chain.prototype = proto;  
            
              function Class() {}  
              Class.prototype = new Chain;  
            
              // inherit the prototype of this Function  
              for(var f in o.prototype) {  
                  Class.prototype[f] = o.prototype[f];  
                  // function has a super function  
                  if(typeof Class.prototype[f] == 'function') Class.prototype[f]._super = proto[f];  
              }  
              o.prototype = Class.prototype;  
              o.prototype.constructor = o;  
            
              o.prototype._parent = b;  
            
              Class.prototype._super = function() {  
          		var c = Class.prototype._super.caller;  
          		  
                  if(!c._super && this._parent) { // Konstruktorcall  
          	    var parent = this._parent, ret;  
                      var proto = o.prototype;  
            
                      this._parent = this._parent.prototype._parent;  
                      ret = parent.apply(this, arguments);  
                      this._parent = parent;  
                      return ret;  
          	} else if(!c._super) throw new Error('Function has no _super function.\n' + c +'');  
                  return c._super.apply(this, arguments)  
              }  
          }  
          
          

          Das ist ein Kompromiss zwischen flexibilität und Geschwindigkeit. Aber es lassen sich Funktionen als Konstruktor nutzen, so wie es in JS momentan vorgesehen ist.

          Struppi.

          1. Hallo Strupi

            Ja so etwas versuche ich zu erreichen, nur will ich es auch verstehen, darum experimentiere ich noch ein bisschen :)

            Gruss Hansi

            1. Ja so etwas versuche ich zu erreichen, nur will ich es auch verstehen, darum experimentiere ich noch ein bisschen :)

              Dann dürfte dich dieser Artikel von molily interessieren, dort wird viel von den notwendigen Grundlagen genau erklärt.

              Struppi.

              1. Dann dürfte dich dieser Artikel von molily interessieren, dort wird viel von den notwendigen Grundlagen genau erklärt.

                Bzw. Organisation von JavaScripten: Konstruktoren, Prototypen und Instanzen aus meiner JavaScript-Doku

                (Der Grundlagen-Artikel ist übrigens eine Übersetzung, Original von Dmitry Soshnikov)

                Mathias

                1. Hallo Mathias

                  Besten Dank!
                  Das zieh ich mir bei der nächsten Gelegenheit rein!

                  Gruss Hansi

                  Bzw. Organisation von JavaScripten: Konstruktoren, Prototypen und Instanzen aus meiner JavaScript-Doku

  2. Wieso funktioniert das nicht???:

    function makeClass(proto){
      var f = proto.init;
      f.protoype = proto;
      return f;
    }
    Person = makeClass({
      init:function(name){
        this.name = name
      },
      alert:function(){
        alert(name)
      }
    })
    Joe = new Person(4);
    Joe.alert();

      
    Weil die Konstruktorfunktion nicht im Kontext mit dem Objekt (proto) aufgerufen wird. Du erzeugst ein Objekt proto.init, das hat aber keine Methode alert()  
      
    Struppi.