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
};
Jedes Objekt ist mit einem Prototyp-Objekt verknüpft. Wenn Sie versuchen, auf eine Eigenschaft zuzugreifen, die nicht existiert, sucht JavaScript im Prototyp-Objekt des Objekts nach dieser Eigenschaft und gibt sie zurück, wenn sie existiert.
El prototype
Eigenschaft eines Funktionskonstruktors bezieht sich auf das Prototyp-Objekt aller Instanzen, die mit dieser Funktion erstellt werden, wenn man new
.
In Ihrem ersten Beispiel fügen Sie eine Eigenschaft hinzu x
zu jeder Instanz, die mit der Option A
Funktion.
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
Im zweiten Beispiel fügen Sie dem Prototyp-Objekt eine Eigenschaft hinzu, die alle Instanzen, die mit A
hinweisen.
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor
Zusammenfassend lässt sich sagen, dass im ersten Beispiel jeder Instanz wird eine Kopie der Funktion zugewiesen . Im zweiten Beispiel eine einzige Kopie der Funktion wird von allen Instanzen gemeinsam genutzt .
Das eigentliche Problem bei der Verwendung von this
anstelle von prototype
ist, dass beim Überschreiben einer Methode der Konstruktor der Basisklasse weiterhin auf die überschriebene Methode verweist. Bedenken Sie dies:
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
gegen:
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
Wenn Sie der Meinung sind, dass dies kein Problem darstellt, dann hängt es davon ab, ob Sie ohne private Variablen leben können und ob Sie erfahren genug sind, um ein Leck zu erkennen, wenn Sie eines sehen. Außerdem ist es lästig, die Konstruktorlogik nach den Methodendefinitionen zu platzieren.
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
gegen:
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
Was ist der Unterschied? => Eine Menge.
Ich denke, die this
Version wird verwendet, um die Verkapselung, d.h. das Verbergen von Daten, zu ermöglichen. Sie hilft dabei, private Variablen zu manipulieren.
Betrachten wir das folgende Beispiel:
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
Nun, die prototype
Struktur kann wie folgt angewendet werden:
Verschiedene Erwachsene haben ein unterschiedliches Alter, aber alle Erwachsenen haben die gleichen Rechte.
Also fügen wir es mit Prototyp hinzu, statt mit diesem.
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
Schauen wir uns nun die Umsetzung an.
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
Ich hoffe, das hilft.
+1 Eine viel weniger komplizierte und anschaulichere Antwort als die anderen. Sie sollten jedoch etwas ausführlicher werden, bevor Sie diese (guten) Beispiele anführen.
Ich bin mir nicht sicher über "diese Version wird verwendet, um eine Kapselung zu ermöglichen, d.h. um Daten zu verstecken". Wenn eine Eigenschaft innerhalb einer Funktion mit "this" wie in "this.myProperty=..." definiert wird, ist eine solche Eigenschaft nicht "privat" und kann von Objekten außerhalb der Klasse mit "new" aufgerufen werden.
Ich weiß, dass diese Frage schon zu Tode beantwortet wurde, aber ich möchte gerne ein konkretes Beispiel für Geschwindigkeitsunterschiede zeigen.
Funktion direkt am Objekt:
function ExampleFn() {
this.print = function() {
console.log("Calling print! ");
}
}
var objects = [];
console.time('x');
for (let i = 0; i < 2000000; i++) {
objects.push(new ExampleFn());
}
console.timeEnd('x');
//x: 1151.960693359375ms
Funktion auf Prototyp:
function ExampleFn() {
}
ExampleFn.prototype.print = function() {
console.log("Calling print!");
}
var objects = [];
console.time('y');
for (let i = 0; i < 2000000; i++) {
objects.push(new ExampleFn());
}
console.timeEnd('y');
//x: 617.866943359375ms
Hier erstellen wir 2.000.000 neue Objekte mit einer print
Methode in Chrome. Wir speichern jedes Objekt in einem Array. Einfügen von print
auf dem Prototyp dauert etwa halb so lang.
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