Richtige Javascript-Vererbung

Lesezeit: 5 Minuten

Ich habe viele Artikel über “Vererbung” in Javascript gelesen. Einige von ihnen verwendet new während andere es empfehlen Object.Create. Je mehr ich lese, desto verwirrter werde ich, da es unendlich viele Varianten zu geben scheint, um das Thema Vererbung zu lösen.

Kann mir jemand freundlicherweise den akzeptiertesten Weg zeigen (oder den Defacto-Standard, falls es einen gibt)?

(Ich möchte ein Basisobjekt haben Model die ich verlängern kann RestModel oder LocalStorageModel.)

Richtige Javascript Vererbung
Bergi

Einfach: Object.create wird nicht in allen Umgebungen unterstützt, kann aber angepasst werden new. Abgesehen davon haben die beiden unterschiedliche Ziele: Object.create erstellt nur ein Objekt, das von einem anderen erbt, während new Auch ruft eine Konstruktorfunktion auf. Verwenden Sie, was angemessen ist.

In deinem Fall scheinst du das zu wollen RestModel.prototype erbt von Model.prototype. Object.create (oder sein Shim) ist dann der richtige Weg, weil Sie nicht a) eine neue Instanz erstellen (einen instanziieren möchten new Model) und b) den Modellkonstruktor nicht aufrufen möchten:

RestModel.prototype = Object.create(Model.prototype);

Wenn Sie den Modellkonstruktor auf RestModels aufrufen möchten, hat das nichts mit Prototypen zu tun. Verwenden call() oder apply() dafür:

function RestModel() {
    Model.call(this); // apply Model's constructor on the new object
    ...
}

  • Warum ist Object.Create besser als new In diesem Fall? Was wäre, wenn ich auch Konstrukteure unterstützen möchte? Und dass der Konstruktor in beiden aufgerufen wird RestModel und Model (Wenn ich eine RestModel). Ich bin normalerweise ein C#-Entwickler, also verstehe ich den Unterschied nicht wirklich. Ich möchte den Basisprototyp definieren und einen Konstruktor verwenden, aber ich verstehe nicht, wie ich beides bekomme?

    – jgauffin

    5. Juni 2012 um 14:11 Uhr


  • Ich denke, diese Antwort fasst es zusammen “Verwenden Sie, was angemessen ist.” Manchmal möchten Sie die Logik im Konstruktor, manchmal nicht. +1

    Benutzer1106925

    5. Juni 2012 um 14:13 Uhr

Richtige Javascript Vererbung
ZER0

JavaScript ist eine OOP-Sprache, die auf Prototypen und nicht auf Klassen basiert. Das ist einer der Gründe für all diese Verwirrung, die Sie sehen können: Viele Entwickler verwenden JS, da es klassenbasiert war.

Daher können Sie viele Bibliotheken sehen, die versuchen, das Paradigma einer klassenbasierten Sprache in JS zu verwenden.

Darüber hinaus fehlen JS selbst einige Eigenschaften, die die Vererbung, auch prototypbasiert, schmerzhaft machen. Zum Beispiel vorher Object.create Es gab keine Möglichkeit, ein Objekt aus einem anderen Objekt zu erstellen (wie es eine auf OOP-Prototypen basierende Sprache tun sollte), sondern nur die Verwendung von a function als Konstrukteur.

Und auch aus diesem Grund gibt es viele Bibliotheken, die versuchen, die Sprache zu „reparieren“, jede auf ihre eigene Art und Weise.

Deine Verwirrung ist also normal. Sagen Sie, der “offizielle” Weg ist die Verwendung prototype Eigentum, functions als Konstruktor und Object.create aus der Instanz des Objekts erstellen. Wie oben erwähnt, ist der Code jedoch in einigen Fällen ausführlich oder es fehlt ihm an Funktionalität, sodass diese Prozedur oft irgendwie umbrochen wird und dann eine Frage des persönlichen Geschmacks wird.

Da Sie von Modell sprechen, können Sie einen Blick darauf werfen Backbone-Modell und sehen Sie, ob dieser Ansatz zu Ihnen passt.

Aktualisieren: Um ein Beispiel zu geben, von dem ich hoffe, dass es Ihnen hilft, es zu verdeutlichen, verwenden Sie hier die alte Schule der Vererbung new:

function Model() {
    this.foo = "foo";
    this.array = [];
}

Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};

function RestModel() {
    this.bar = "bar";
}

RestModel.prototype = new Model;
RestModel.prototype.bar = ""

var myModel = new RestModel();

Hier nun die Probleme:

  1. Der Konstrukteur von Model wird einmal aufgerufen, nur wenn die RestModel.prototype eingestellt ist. deshalb, die foo Eigentum für alle RestModel Instanz wird “foo” sein.
  2. Nicht nur das, sondern alle RestModel Instanzen teilen sich dieselbe Instanz desselben Arrays in this.array Eigentum. Wenn Sie eine Instanz von erstellen Model direkt haben Sie für jede Instanz eine neue Instanz des Arrays.
  3. myModel.constructor ist Model anstatt RestModel. Das liegt daran, dass wir überschreiben prototype mit einer neuen Instanz von Modeldas beinhaltet constructor ist gleich Model.
  4. Wenn Sie eine neue Instanz von haben möchten RestModel mit einem faulen Aufruf des Konstruktors, ist nicht möglich.

Ich denke, es gibt die Hauptpunkte, natürlich sind sie nicht die einzigen. Also, wie kann man diese Probleme lösen? Wie gesagt, viele Leute haben das bereits getan, und sie erstellen Bibliotheken und Frameworks, um die Ausführlichkeit einzuschränken. Aber um eine Idee zu haben:

function Model() {
    this.foo = "foo";
    this.array = [];
}

Model.prototype.foo = "";
Model.prototype.array = null;
Model.prototype.doNothing = function() {};

function RestModel() {
    Model.call(this);

    this.bar = "bar";
}

RestModel.prototype = Object.create(Model.prototype);
RestModel.prototype.constructor = RestModel;
RestModel.prototype.bar = ""

var myModel = new RestModel();

// for lazy constructor call
var anotherModel = Object.create(RestModel.prototype);

RestModel.call(anotherModel);

Beachten Sie, dass, wenn Sie nicht verwenden möchten prototype oder function als Konstruktor, mit Object.create Das kannst du machen:

var Model = {
    foo: "",
    array: null,
    doNothing: function() {}
}

var RestModel = Object.create(Model);

RestModel.bar = "";

var myModel = Object.create(RestModel);

// Assuming you have to set some default values
initialize(RestModel);

Oder:

var Model = {
    foo: "",
    array: null,
    doNothing: function() {},

    init : function () {
        this.foo = "foo";
        this.array = [];
    },
}

var RestModel = Object.create(Model);

RestModel.bar = "";
RestModel.init = function () {
    Model.init.call(this);

    this.bar = "bar";
}

var myModel = Object.create(RestModel);

myModel.init();

In diesem Fall ahmen Sie im Grunde den Konstruktor nach. Sie können auch eine passieren descriptor zu Object.create (siehe die Dokumente), aber es wird ausführlicher. Die meisten Leute verwenden eine Art von extend Funktion oder Methode (wie Sie wahrscheinlich im Backbone-Beispiel gesehen haben).

Ich hoffe es hilft!

  • Welches Beispiel empfehlen Sie mir?

    – jgauffin

    5. Juni 2012 um 17:34 Uhr

  • Alle von ihnen sind gültig, aber in der einen oder anderen Form werden sie ausführlich sein. Sie können sich vorstellen, ob RestModel hat zum Beispiel viele neue Eigenschaften oder Methoden. Das meinte ich, als ich sagte, dass JS noch etwas fehlt. Um die Ausführlichkeit zu entfernen, oder Sie entscheiden sich, Bibliotheken von Drittanbietern zu verwenden, oder Sie erstellen ein paar Hilfsfunktionen, um dies zu tun. Ich werde das Reine vermeiden new Ansatz (der erste) und sich gerade für den 2. oder 3. entschieden haben, hängt davon ab, ob Sie sich wohler fühlen, etwas zu haben, das einer “Klasse” “ähnelt” (also der 2.) oder nicht (3.).

    – ZER0

    5. Juni 2012 um 17:49 Uhr

929570cookie-checkRichtige Javascript-Vererbung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy