Der erste Unterschied kann wie folgt zusammengefasst werden: this
Bezieht sich auf die Instanz der Klasse. prototype
bezieht sich auf Definition .
Nehmen wir an, wir haben folgende Klasse:
var Flight = function ( number ) { this.number = number; };
Hier hängen wir also this.number
an jeder Instanz der Klasse, und es ist sinnvoll, weil jede Flight
ihre eigene Flugnummer haben sollte.
var flightOne = new Flight( "ABC" );
var flightTwo = new Flight( "XYZ" );
Im Gegensatz dazu prototype
definiert eine einzige Eigenschaft , die durch alle Instanzen zugegriffen werden kann.
Wenn wir nun die Flugnummer erhalten möchten, können wir einfach das folgende Snippet schreiben und alle unsere Instanzen erhalten eine Referenz auf dieses neu erstellte Objekt.
Flight.prototype.getNumber = function () { return this.number; };
Der zweite Unterschied betrifft die Art und Weise, wie JavaScript nach einer Eigenschaft eines Objekts sucht. Wenn Sie suchen , Object.whatever
geht JavaScript den ganzen Weg bis zum Hauptobjekt Objekt (das Objekt , dass alles andere aus geerbt hat), und sobald sie eine Übereinstimmung findet , wird es zurückgeben oder es nennen.
Dies geschieht jedoch nur für die prototypisierten Eigenschaften. Wenn Sie also eine höhere Ebene haben this.whatever
, wird JavaScript diese nicht als Übereinstimmung betrachten und die Suche fortsetzen.
Mal sehen, wie es in der Realität passiert.
Beachten Sie zunächst, dass [fast] alles Objekte in JavaScript sind. Versuche dies:
typeof null
Nun wollen wir sehen , was in einem ist Object
( man beachte die Groß- O
und .
am Ende). In den Entwicklertools von Google Chrome erhalten .
Sie beim Aufrufen von eine Liste der verfügbaren Eigenschaften in diesem bestimmten Objekt.
Object.
Tun Sie jetzt dasselbe für Function
:
Function.
Möglicherweise bemerken Sie die name
Methode. Geht einfach und macht es an und lasst uns sehen, was passiert:
Object.name
Function.name
Nun erstellen wir eine Funktion:
var myFunc = function () {};
Und mal sehen, ob wir die name
Methode auch hier haben:
myFunc.name
Sie sollten eine leere Zeichenfolge erhalten, aber das ist in Ordnung. Sie sollten keinen Fehler oder eine Ausnahme erhalten.
Jetzt wollen Object
wir etwas zu diesem gottähnlichen hinzufügen und sehen, ob wir es auch an anderen Orten bekommen?
Object.prototype.test = "Okay!";
Und los geht's:
Object.prototype.test
Function.prototype.test
myFunc.prototype.test
In allen Fällen sollten Sie sehen "Okay!"
.
In Bezug auf die Vor- und Nachteile jeder Methode können Sie Prototyping als "effizientere" Methode betrachten, da es eine Referenz für jede Instanz enthält, anstatt die gesamte Eigenschaft in jedem Objekt zu kopieren. Auf der anderen Seite ist es ein Beispiel für enge Kopplung, die ein großes Nein ist, bis Sie den Grund wirklich rechtfertigen können. this
ist ziemlich kompliziert, da es für den Kontext relevant ist. Sie können viele gute Ressourcen kostenlos im Internet finden.
Alles in allem sind beide Möglichkeiten nur Sprachwerkzeuge und es hängt wirklich von Ihnen und dem Problem ab, das Sie zu lösen versuchen, um herauszufinden, was besser passt.
Wenn Sie eine Eigenschaft benötigen, die für jede Instanz einer Klasse relevant ist, verwenden Sie this
. Wenn Sie eine Eigenschaft benötigen, die auf jeder Instanz gleich funktioniert, verwenden Sie prototype
.
Aktualisieren
In Bezug auf Ihre Beispiel-Snippets ist der erste ein Beispiel für Singleton , daher ist es sinnvoll, ihn im Objektkörper zu verwenden this
. Sie können Ihr Beispiel auch verbessern, indem Sie es so modular gestalten (und Sie müssen es nicht immer verwenden this
).
/* Assuming it will run in a web browser */
(function (window) {
window.myApp = {
...
}
})( window );
/* And in other pages ... */
(function (myApp) {
myApp.Module = {
...
}
})( myApp );
/* And if you prefer Encapsulation */
(function (myApp) {
myApp.Module = {
"foo": "Foo",
"bar": function ( string ) {
return string;
},
return {
"foor": foo,
"bar": bar
}
}
})( myApp );
Ihr zweites Snippet macht nicht viel Sinn, weil Sie es zuerst verwenden this
und später versuchen, es zu hacken prototype
, was nicht funktioniert, weil es this
Vorrang hat prototype
. Ich bin mir nicht sicher, welche Erwartungen Sie an diesen Code hatten und wie er funktionierte, aber ich empfehle Ihnen dringend, ihn umzugestalten.
Aktualisieren
Um näher darauf this
einzugehen, prototype
kann ich Ihnen ein Beispiel zeigen und erklären, wie es erklärt werden kann, aber ich habe keine externe Ressource, um es zu sichern.
Das Beispiel ist sehr einfach:
var myClass = function () { this.foo = "Foo"; };
myClass.prototype.foo = "nice try!";
myClass.prototype.bar = "Bar";
var obj = new myClass;
obj.foo; // Still contains "Foo" ...
obj.bar; // Contains "Bar" as expected
Die Erklärung ist, wie wir wissen, this
kontextbezogen. Es entsteht also erst, wenn der Kontext bereit ist. Wann ist der Kontext fertig? Wenn die neue Instanz erstellt wird! Sie sollten den Rest jetzt erraten! Das bedeutet, dass es zwar eine prototype
Definition gibt, es jedoch this
sinnvoller ist, Vorrang zu haben, da es sich nur um die neue Instanz handelt, die in diesem Moment erstellt wird.