Was ist der Unterschied zwischen
var A = function () {
this.x = function () {
//do something
};
};
et
var A = function () { };
A.prototype.x = function () {
//do something
};
Was ist der Unterschied zwischen
var A = function () {
this.x = function () {
//do something
};
};
et
var A = function () { };
A.prototype.x = function () {
//do something
};
Ich möchte Ihnen eine umfassendere Antwort geben, die ich in einem JavaScript-Kurs gelernt habe.
Die meisten Antworten haben den Unterschied bereits erwähnt, d.h. beim Prototyping wird die Funktion mit allen (zukünftigen) Instanzen geteilt. Bei der Deklaration der Funktion in der Klasse wird hingegen für jede Instanz eine Kopie erstellt.
Im Allgemeinen gibt es kein Richtig oder Falsch, es ist eher eine Frage des Geschmacks oder eine Design-Entscheidung je nach Ihren Anforderungen. Der Prototyp ist jedoch die Technik, die zur objektorientierten Entwicklung verwendet wird, wie Sie hoffentlich am Ende dieser Antwort sehen werden.
Sie haben in Ihrer Frage zwei Muster aufgezeigt. Ich werde versuchen, zwei weitere zu erklären und gegebenenfalls die Unterschiede zu erläutern. Sie können sie gerne bearbeiten/erweitern. In allen Beispielen geht es um ein Autoobjekt, das einen Standort hat und sich bewegen kann.
Ich bin nicht sicher, ob dieses Muster heute noch relevant ist, aber es existiert. Und es ist gut, es zu kennen. Man übergibt einfach ein Objekt und eine Eigenschaft an die Decorator-Funktion. Der Dekorator gibt das Objekt mit Eigenschaft und Methode zurück.
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
Eine Funktion in JavaScript ist ein spezialisiertes Objekt. Eine Funktion kann nicht nur aufgerufen werden, sondern sie kann auch Eigenschaften wie jedes andere Objekt speichern.
In diesem Fall Car
ist eine Funktion ( auch piense en Objekt ), die in gewohnter Weise aufgerufen werden können. Sie hat eine Eigenschaft methods
(das ist ein Objekt mit einer move
Funktion). Wenn Car
aufgerufen wird, wird die extend
Funktion aufgerufen, die etwas zaubert und die Car
Funktion (think object) mit den Methoden, die in methods
.
Dieses Beispiel ist zwar anders, kommt aber dem ersten Beispiel in der Frage am nächsten.
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
Die ersten beiden Muster erlauben eine Diskussion über die Verwendung von Techniken zur Definition gemeinsamer Methoden oder die Verwendung von Methoden, die inline im Körper des Konstruktors definiert sind. In beiden Fällen hat jede Instanz ihre eigene move
Funktion.
Das prototypische Muster eignet sich nicht für die gleiche Untersuchung, da die gemeinsame Nutzung von Funktionen über eine prototypische Delegation das eigentliche Ziel des prototypischen Musters ist. Wie bereits erwähnt, wird erwartet, dass es einen besseren Speicherplatzbedarf hat.
Es gibt jedoch einen Punkt, der interessant zu wissen ist: Jeder prototype
Objekt hat eine praktische Eigenschaft constructor
, die auf die Funktion (think object) zurückverweist, an die sie angehängt wurde.
Zu den letzten drei Zeilen:
In diesem Beispiel Car
Links zu den prototype
Objekt, das sich über constructor
a Car
selbst, d.h. Car.prototype.constructor
es Car
selbst. So können Sie herausfinden, welche Konstruktorfunktion ein bestimmtes Objekt erstellt hat.
amy.constructor
scheitert und wird daher delegiert an Car.prototype
die über die Eigenschaft Konstruktor verfügt. Und so amy.constructor
es Car
.
Außerdem, amy
ist ein instanceof
Car
. El instanceof
Operator funktioniert, indem er prüft, ob das Prototypobjekt des rechten Operanden ( Car
) kann an beliebiger Stelle im Prototyp des linken Operanden gefunden werden ( amy
) Kette.
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
Manche Entwickler sind anfangs etwas verwirrt. Siehe untenstehendes Beispiel:
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
El instanceof
Operator kehrt zurück false
denn Dog
ist der Prototyp nirgendwo in fido
Prototyp der Kette. fido
ist ein einfaches Objekt, das mit einem Objektliteral erstellt wird, d.h. es delegiert einfach an Object.prototype
.
Dies ist eigentlich nur eine andere Form des prototypischen Musters in vereinfachter Form und vertrauter für diejenigen, die zum Beispiel in Java programmieren, da es die new
Konstrukteur.
Es tut dasselbe wie im prototypischen Muster, es ist nur syntaktischer Zucker über dem prototypischen Muster.
Der Hauptunterschied besteht jedoch darin, dass es in JavaScript-Engines implementierte Optimierungen gibt, die nur bei Verwendung des pseudoklassischen Musters gelten. Betrachten Sie das pseudoklassische Muster als eine wahrscheinlich schnellere Version des prototypischen Musters; die Objektbeziehungen sind in beiden Beispielen die gleichen.
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
Schließlich sollte es nicht allzu schwierig sein, zu erkennen, wie objektorientierte Programmierung durchgeführt werden kann. Es gibt zwei Abschnitte.
Ein Abschnitt, der gemeinsame Eigenschaften/Methoden im Prototyp (Kette) definiert.
Und einen weiteren Abschnitt, in dem Sie die Definitionen eintragen, die die Objekte voneinander unterscheiden ( loc
Variable in den Beispielen).
Dies ermöglicht es uns, Konzepte wie Superklasse oder Unterklasse in JavaScript anzuwenden.
Sie können gerne etwas hinzufügen oder bearbeiten. Wenn es vollständiger ist, könnte ich daraus vielleicht ein Community-Wiki machen.
Ich will den sehr gründlichen Beitrag nicht schlecht machen, aber ich dachte, OO und prototypische Vererbung seien im Wesentlichen unterschiedliche Denkschulen.
Ich bin mir nicht ganz sicher. Viele sagen einfach, dass die prototypische Philosophie einfach anders ist, und viele versuchen, sie mit OO zu vergleichen, weil das die Denkschule ist, an die viele gewöhnt sind.
Ich glaube, dass @Matthew Crumley Recht hat. Sie sind funktionell wenn nicht sogar strukturell gleichwertig. Wenn Sie Firebug verwenden, um die Objekte zu betrachten, die mit new
können Sie sehen, dass sie identisch sind. Meine Präferenz wäre jedoch die folgende. Ich vermute, dass es einfach mehr dem entspricht, was ich aus C#/Java gewohnt bin. Das heißt, man definiert die Klasse, definiert die Felder, den Konstruktor und die Methoden.
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDITAR Ich wollte damit nicht andeuten, dass der Geltungsbereich der Variablen privat ist, ich wollte nur veranschaulichen, wie ich meine Klassen in Javascript definiere. Der Variablenname wurde geändert, um dies widerzuspiegeln.
_instance_var wie in der initialize
y x methods do not refer to the
_instance_var`-Eigenschaft auf einer A
Instanz, sondern zu einer globalen Instanz. verwenden this._instance_var
wenn Sie die Funktion _instance_var
Eigenschaft eines A
Instanz.
Wie bereits in anderen Antworten erwähnt, ist dies eine Frage der Leistung, da die Funktion im Prototyp von allen Instanziierungen gemeinsam genutzt wird, anstatt dass die Funktion für jede Instanziierung neu erstellt wird.
Ich habe ein jsperf zusammengestellt, um dies zu zeigen. Es gibt einen dramatischen Unterschied in der Zeit, die es braucht, um die Klasse zu instanziieren, obwohl es wirklich nur relevant ist, wenn Sie viele Instanzen machen.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
23 Stimmen
Verwandt: Definieren von Methoden über Prototyp vs. Verwendung im Konstruktor - wirklich ein Leistungsunterschied? und gute Antworten auf Duplikate: Deklaration der Methode im Konstruktor oder am Prototyp , dies vs. Prototyp
0 Stimmen
Das Konzept des Schlüsselworts THIS wird hier explizit erläutert scotch.io/@alZami/verstehen-dieses-in-javascript
3 Stimmen
Die Lektüre "dieses" Threads zeigt, wie schrecklich JS ist und wie sehr seine Prinzipien für viele Entwickler unklar sind. Was genau ist falsch an einfacher zu verstehenden Sprachen? Ich denke, es ist an der Zeit, dass die Entwickler ihre Stimme erheben, um verwirrende Technologien abzulehnen, die keinen oder nur einen geringen Nutzen für das Geschäft oder die Entwicklungsarbeit haben.
1 Stimmen
Am Objekt:
a1.x !== a2.x
; auf Prototyp:a1.x === a2.x