Ich verwende das folgende Paradigma für die Deklaration von Klassen:

var myNamespace = myNamespace || {};
(function () {
    myNamespace.MyClass = function () {
        if (!(this instanceof myNamespace.MyClass)) {
            return new myNamespace.MyClass();
        }

        this.field = 17;

        this.foo = this.foo.bind(this);
        this.bar = this.bar.bind(this);
    };

    myNamespace.MyClass.prototype.foo = function(){
        console.log(this.field + 1);
    };

    myNamespace.MyClass.prototype.bar = function(){
        console.log(this.field + 2);
    };
})();

Ich benutze prototype, um zu vermeiden, dass die Objektmethoden bei jeder Instanziierung neu deklariert werden, und um den Code ein bisschen sauberer zu machen - indem ich die Klassenfelder von seiner Logik trenne.
Ich rufe bei jeder Methode bind auf, um böse Fehler zu vermeiden, bei denen this innerhalb der Methoden den falschen Weg weist.

Es funktioniert, ist aber fehleranfällig - ich muss daran denken, bei jeder Methode bind aufzurufen, und es ist zu ausführlich, insbesondere wenn es mehr als zwei Methoden gibt.

Gibt es eine sauberere * Möglichkeit, diese Art von Funktionen zu deklarieren (an die this ihres Typs gebunden und auf dem prototype deklariert)?

* Ich weiß, dass "sauber" nicht gut definiert ist - Eine einfache Metrik wäre die Codelänge.

0
seldary 20 Nov. 2013 im 00:38

3 Antworten

Beste Antwort

Sie sollten Ihre Methoden nicht so binden - Sie erstellen auf jeder Instanz neue Funktionen, wenn Sie wirklich nur die Methoden auf dem Prototyp haben sollten, um Speicherplatz zu sparen. Wenn Sie 100 Instanzen erstellen, erstellen Sie 200 neue Funktionen! Ein einfaches Muster wie dieses ist häufiger und funktioniert gut:

var myNamespace = myNamespace || {};
myNamespace.MyClass = (function() {
  function MyClass() {
    this.field = 17;
  }

  MyClass.prototype = {
    constructor: MyClass,
    foo: function() {
      console.log(this.field + 1);
    },
    bar: function(){
      console.log(this.field + 2);
    }
  };

  return MyClass;
}());
4
sbking 19 Nov. 2013 im 20:53

Fügen Sie Ihrem Namespace hinzu, nachdem Sie Ihre Klasse deklariert haben:

var myNamespace = myNamespace || {};
(function () {
    var MyClass = function () {
        this.field = 17;
    };

    MyClass.prototype.foo = function(){
        console.log(this.field + 1);
    };

    MyClass.prototype.bar = function(){
        console.log(this.field + 2);
    };
    this.MyClass = MyClass;

}).call(myNamespace);

Durch Aufrufen des IIFE mit dem Namespace als Gültigkeitsbereich können Sie das Modul sauber halten, indem Sie die Klasse für das Objekt this verfügbar machen.

1
Jivings 19 Nov. 2013 im 20:46

Sie können einige der Prototypdefinitionen in einer einzigen Zuweisung komprimieren und Ihren Namespace an einen Funktionsaufruf übergeben.

var myNamespace = myNamespace || {};
(function () {
    function MyClass() { 
        this.field = 17;
    };

    MyClass.prototype = {
        foo: function () {
            console.log(this.field + 1);
        },

        bar: function () {
            console.log(this.field + 2);
        }
    };
})(myNamespace);
0
Nick 19 Nov. 2013 im 20:50