2009-07-02 9 views
22
var A=function(){ 
}; 

$.extend(A.prototype, { 
    init:function(){ 
     alert('A init'); 
    } 
}); 
var B=function(){ 

}; 

$.extend(B.prototype,A.prototype,{ 
    init:function(){ 
     alert('B init'); 
    } 
}); 
var p=new A(); 
p.init(); 
var x=new B(); 
x.init(); 

ist die oben genannte der beste Weg, um Klasse und Vererbung in jQuery zu erstellen? Wie starte ich in B's init die Init von Eltern (ähnlich wie super.init() in OO-Sprachen)?jquery Klasse Vererbung

+0

Suche nach einem Weg dies zu tun, keine der Antworten befriedigt mich. Ich biete unten eine alternative jQuery-Lösung an, die $ .extend und $ .proxy nutzt. – xtempore

Antwort

19

Für OO ist es am besten, außerhalb von jQuery zu suchen. jQuery basiert auf Sammlungen, die von Selektoren zurückgegeben werden.

Wenn Sie Klassen möchten, sind einige Optionen Base2, Joose und JS.Class.

+13

Wie ist das eine akzeptierte Antwort? F: "Ist das der beste Weg, X in jQuery zu machen?" A: "Verwenden Sie nicht jQuery." Für einige von uns ist das nicht wirklich eine Option. – umassthrower

+10

@umassthrower Der Beantworter schlägt nicht vor, dass er jQuery nicht verwenden soll, er schlägt vor, dass jQuery keine Lösung für Klassen bietet. Jede der genannten Optionen kann mit jQuery koexistieren. – undefined

5

Wie Eltern Methoden aufzurufen:

var B=function(){ 
    A.call(this); 
}; 

$.extend(B.prototype,A.prototype,{ 
     init:function(){ 
       A.prototype.init.call(this); 
       alert('B init'); 
     } 
}); 
5

Wenn Sie wollen nicht auf anderen Bibliotheken abhängen, können Sie dies tun:

function A() {} 
A.prototype.foo = function() {}; 

function B() { 
    A.call(this); 
    //Or, if there are arguments that need to be passed to A(), 
    //this might be preferable: 
    //A.apply(this, arguments); 
} 

B.prototype = new A(); 

//Or, if the browser supports ECMAScript 5 and/or you have a shim for Object.create, 
//it would be better to do this: 
B.prototype = Object.create(A.prototype); 

$.extend(B.prototype, { 
    //set the constructor property back to B, otherwise it would be set to A 
    constructor: B, 
    bar: function() {} 
}); 

Stellen Sie sicher, alle Eigenschaften im Konstruktor zu definieren, anstatt auf dem Prototyp, zB:

function A() { 
    this.baz = null; 
} 

Dies vermeidet unbeabsichtigt gemeinsame Prototypeigenschaften.

Es gibt einige Bibliotheken, die prototypische Vererbung einfacher machen:

Anmerkungen:

  • Jedes Mal, wenn ein Prototyp ersetzt wird, einschließlich der Erweiterung, ist es eine bewährte Methode, seine Konstruktoreigenschaft auf den richtigen Konstruktor zurückzusetzen. Deshalb haben wir B.prototype.constructor auf B gesetzt Wenn Sie A.prototype ersetzten sollten Sie es wie folgt tun:

...

A.prototype = { 
    constructor: A, 
    foo: function() {} 
    //other methods... 
} 
  • B.prototype = Object.create(A.prototype) wird bevorzugt über B.prototype = new A() weil es Ihnen hilft, es früh zu erkennen, wenn Sie vergessen haben, A() von B() Konstruktor aufzurufen; es erlaubt auch A(), erforderliche Parameter zu haben. Sie benötigen ein Shim für ältere Browser; Das einfachste Shim (obwohl es die vollständige Object.create-Spezifikation nicht unterstützt) befindet sich am Ende dieser Seite: .
0

Ich benutze das gleiche Muster und ich mag seine Prägnanz.

Über das Fehlen des "Super" -Schlüsselwortes ist das nicht wirklich ein Problem. Dank des Function.prototype.call() - Operators können Sie jede Funktion im Kontext eines beliebigen Objekts aufrufen. So ist die Sequenz zu nennen A.prototype.init() von B.prototype.init() ist:

A.prototype.init.call(this, some parameters ...);

Auch vergessen Sie nicht, dass Sie einen Konstruktor von B Konstruktor wie folgt aufrufen können:

B = function(key, name) { 
    A.call(this, key); 
    this.name = name; 
}; 

Ein experimentierter JS-Codierer wird wissen, was passiert.

Also zum Schluss: nicht perfekt, aber nahe genug.

0

Ich suchte nach etwas Ähnlichem. Keine der Antworten gegeben wirklich gefiel mir, so hatte ich endlich einen Riss an es selbst ...

http://jsfiddle.net/tn9upue0/1/

Beispiel Klassen

  • $ .Animal() erzeugt ein generisches Tier , mit einem Standardwert von 4 Beinen, dass kann ein Name in seinen Optionen übergeben werden, und kann sich selbst beschreiben. $ .Dog() ist eine Unterklasse von Animal, die "woof" lautet und möglicherweise einige Tricks kennt. $ .Cat() ist eine Unterklasse von Animal, die "miau" geht. $ .Bird() ist eine Unterklasse von Animal, die 2 Beine hat und "tweet" geht.

Klasse Implementierung

  • Jedes Tier Unterklasse erstellt eine Instanz von $ .Animal Eltern genannt, , die später verwendet werden können Methoden der Eltern zu nennen. Beim Aufrufen einer übergeordneten Methode kann der Kontext wichtig sein. Wenn dies der Fall ist, sollte die Methode über $ .proxy() aufgerufen werden, wobei dies als Kontext übergeben wird.

Beispiel Ausgabe

Mein Name ist unbekannt. Ich bin ein Tier mit 4 Beinen.

Mein Name ist Rover. Ich bin ein Tier mit 4 Beinen. Ich sage "Wau". Ich kann sitzen, bleiben und mich umdrehen.

Mein Name ist Fäustlinge. Ich bin ein Tier mit 4 Beinen. Ich sage "Miau".

Mein Name ist unbekannt. Ich bin ein Tier mit 2 Beinen. Ich sage "tweeten".

Beispielcode

$.Animal = function (options) { 
    return { 
     options: options || {}, 

     _getName: function() { 
      return this.options.name || 'unknown'; 
     }, 

     _getLegs: function() { 
      return 4; 
     }, 

     describe: function() { 
      return 'My name is ' + this._getName() + '. I am an animal with ' + this._getLegs() + ' legs.'; 
     } 
    } 
}; 

$.Dog = function (options) { 
    var parent = $.Animal(options); 
    return $.extend({}, parent, { 
     describe: function() { 
      var s = $.proxy(parent.describe, this)() + ' I say "woof".'; 
      if (this.options.tricks) { 
       s += ' I can ' + this.options.tricks + '.'; 
      } 
      return s; 
     } 
    }); 
}; 

$.Cat = function (options) { 
    var parent = $.Animal(options); 
    return $.extend({}, parent, { 
     describe: function() { 
      return $.proxy(parent.describe, this)() + ' I say "meow".'; 
     } 
    }); 
}; 

$.Bird = function (options) { 
    var parent = $.Animal(options); 
    return $.extend({}, parent, { 
     _getLegs: function() { 
      return 2; 
     }, 

     describe: function() { 
      return $.proxy(parent.describe, this)() + ' I say "tweet".'; 
     } 
    }); 
}; 

var animal = $.Animal(), 
    rover = $.Dog({name: 'Rover', tricks: 'sit, stay, and roll over'}), 
    mittens = $.Cat({name: 'Mittens'}), 
    bird = $.Bird(); 
$('#out').html(
    animal.describe() + '<br>' + 
     rover.describe() + '<br>' + 
     mittens.describe() + '<br>' + 
     bird.describe() 
);