Warum ist es notwendig, dass die Prototyp-Konstruktor?
In der Abschnitt über Vererbung in der MDN-Artikel Einführung in die objektorientierte Javascript, bemerkte ich, dass Sie legen Sie den Prototyp.Konstruktor:
//correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
Tut dies, dienen alle wichtigen Zweck? Ist es okay, es zu unterlassen?
Froh, dass Sie gefragt, dies: ich lese die gleichen Unterlagen gestern und war neugierig auf die Hintergründe explizit Einstellung der Konstruktor als gut.
Ich musste nur darauf hinweisen, diese Frage ist nun verlinkt in dem Artikel, den Sie verlinkt werden!
nichts ist notwendig
Die
Ich musste nur darauf hinweisen, diese Frage ist nun verlinkt in dem Artikel, den Sie verlinkt werden!
nichts ist notwendig
Die
subclass.prototype.constructor
auf parent_class
wenn Sie nicht schreiben subclass.prototype.constructor = subclass
; Das heißt, mit subclass.prototype.constructor()
direkt zu einem unerwarteten Ergebnis.InformationsquelleAutor trinth | 2011-12-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist nicht immer notwendig, aber es hat seine nutzt. Nehmen wir an, wir wollten eine copy-Methode auf der Basis
Person
Klasse. Wie diese:Nun, was passiert, wenn wir einen neuen
Student
und kopieren?Die Kopie ist nicht eine Instanz von
Student
. Dies ist, weil Sie (ohne explizite Prüfungen), hätten wir keine Möglichkeit, wieder eineStudent
Kopie von der "Basis" - Klasse. Können wir nur zurückgebenPerson
. Wenn jedoch mussten wir einen reset der Konstruktor:...dann funktioniert alles wie erwartet:
constructor
Attribut hat keine spezielle Bedeutung in JS, also kann man genauso gut nennen esbananashake
. Der einzige Unterschied ist, dass der Motor automatisch initialisiertconstructor
auff.prototype
wenn Sie deklarieren eine Funktionf
. Es kann jedoch überschrieben werden jeder Zeit.Ich bekomme dein Punkt, aber die Tatsache, dass der Motor automatisch initialisiert
constructor
bedeutet, dass es nicht haben eine Besondere Bedeutung in JS, so ziemlich per definition.Ich möchte nur klarstellen, dass der Grund, warum das Verhalten, das Sie so funktioniert ist, weil man
return new this.constructor(this.name);
stattreturn new Person(this.name);
. Dathis.constructor
ist dieStudent
- Funktion (, da Sie es mitStudent.prototype.constructor = Student;
), diecopy
Funktion endet Aufruf derStudent
Funktion. Ich bin nicht sicher, was Ihre Absicht war, mit der//just as bad
Kommentar.was meinst du mit "//genauso schlecht"?
Ich denke ich bekomme es. Was aber, wenn die
Student
Konstruktor Hinzugefügt hatte ein zusätzliches argument wie:Student(name, id)
? Wir haben dann zu überschreiben, diecopy
Funktion, den Aufruf derPerson
version von innerhalb es, und dann auch das kopieren der zusätzlichenid
Eigenschaft?InformationsquelleAutor Wayne Burkett
Ja und Nein.
In ES5 und früher, JavaScript nicht verwenden
constructor
für alles. Es definiert, dass das Standard-Objekt in einer Funktionprototype
Eigenschaft haben würde, und es würde verweisen zurück auf die Funktion, und , war es. Nichts anderes in der Spezifikation verwiesen wird.Geändert, dass in ES2015 (ES6), der seine Verwendung in Bezug auf Vererbung Hierarchien. Zum Beispiel,
Versprechen#
verwendet dieconstructor
Eigenschaft, die Versprechen, die Sie nennen, auf (über SpeciesConstructor) beim Bau des neuen Versprechen, um zurückzukehren. Es ist auch involviert in die subtypisierung arrays (über ArraySpeciesCreate).Außerhalb der Sprache selbst, manchmal sind die Leute es benutzen würden, wenn Sie versuchen zu bauen generische "Klon" - Funktionen, oder einfach nur in der Regel, wenn Sie wollte, zu finden, was Sie glaubten, wäre die Objekt-Konstruktor-Funktion. Meine Erfahrung ist, dass Sie es ist selten, aber manchmal sind die Leute verwenden es.
Es ist es standardmäßig, Sie müssen nur steckte es zurück, wenn Sie ersetzen das Objekt an eine Funktion
prototype
Eigenschaft:Wenn Sie dies nicht tun:
...dann
Student.prototype.constructor
erbt vonPerson.prototype
die (vermutlich) hatconstructor = Person
. So ist es irreführend. Und natürlich, wenn Sie Unterklassen von etwas, das es verwendet (wiePromise
oderArray
) und nicht mitclass
1 (übernimmt das für Sie), werden Sie wollen, stellen Sie sicher, dass Sie es richtig. Also im Grunde: Es ist eine gute Idee.Es ist okay, wenn nichts in deinem code (oder code-Bibliothek) verwendet. Ich habe immer sichergestellt war es richtig verdrahtet.
Natürlich mit ES2015 (aka ES6)'s
class
Schlüsselwort, die meisten der Zeit, wir haben es genutzt, wir nicht mehr, denn es werden für uns, wenn wir1 "...wenn Sie Erben etwas, das es verwendet (wie
Promise
oderArray
) und nicht mitclass
..." — Es ist möglich zu tun, aber es ist eine echte Schmerzen (und ein bisschen albern). Verwenden SieReflektieren.konstruieren
.InformationsquelleAutor T.J. Crowder
TLDR; Nicht super notwendig, aber wird wohl langfristig helfen, und es ist genauer, um so zu tun.
HINWEIS: Viel bearbeitet, wie meine Vorherige Antwort war verwirrend geschrieben und hatte einige Fehler, die ich vergessen in meiner Eile zu beantworten. Danke an diejenigen, die darauf hinwies, einige schlimme Fehler.
Grundsätzlich ist es zu Draht subclassing korrekt in Javascript. Wenn wir eine Unterklasse, haben wir einige abgefahrene Dinge, um sicherzustellen, dass die prototypal delegation ordnungsgemäß funktioniert, einschließlich das überschreiben einer
prototype
Objekt. Überschreiben einerprototype
Objekt enthält dieconstructor
, so dass wir dann beheben müssen Sie die Referenz.Lassen Sie uns schnell gehen, wie 'Klassen' in ES5 Arbeit.
Lassen Sie uns sagen, Sie haben eine Konstruktor-Funktion und seinem Prototyp:
Beim Aufruf des Konstruktors instanziiert, sagen
Adam
:Den
new
- Schlüsselwort aufgerufen wird, mit "Person" im Grunde läuft die Person Konstruktor mit ein paar zusätzlichen Zeilen code:Wenn wir
console.log(adam.species)
der lookup fehl amadam
Instanz, das prototypal Kette um seinen.prototype
, diePerson.prototype
- undPerson.prototype
hat eine.species
Eigenschaft, so ist der lookup erfolgreich sein wird, beiPerson.prototype
. Es wird dann melden Sie'human'
.Hier, die
Person.prototype.constructor
Recht zuPerson
.So, nun der interessante Teil, die so genannte 'Unterklassen'. Wenn wir schaffen wollen eine
Student
Klasse, ist eine Unterklasse derPerson
Klasse mit einigen zusätzlichen änderungen, die wir brauchen werden, um sicherzustellen, dass dieStudent.prototype.constructor
Punkte, um Studenten für die Richtigkeit.Es nicht, dies von selbst. Wenn Sie eine Unterklasse der code sieht wie folgt aus:
Aufrufen
new Student()
hier würde zurückgeben, ein Objekt mit all den Eigenschaften, die wir wollen. Hier, wenn wir überprüfeneve instanceof Person
, würde es wiederfalse
. Wenn wir versuchen, aufeve.species
, würde es wiederundefined
.In anderen Worten, wir müssen Draht, delegation, so dass
eve instanceof Person
gibt true zurück, und so, dass Instanzen vonStudent
delegieren richtig zuStudent.prototype
, und dannPerson.prototype
.ABER da wir benennen es mit der
new
Stichwort, denken Sie daran, was dieser Aufruf fügt? Es nennen würdeObject.create(Student.prototype)
ist, wie wir eingerichtet, dass delegational Beziehung zwischenStudent
undStudent.prototype
. Beachten Sie, dass es jetztStudent.prototype
leer ist. So suchen.species
eine Instanz vonStudent
scheitern würden, wie es die Delegierten nurStudent.prototype
, und die.species
Eigenschaft nicht vorhanden ist, aufStudent.prototype
.Wenn wir das tun, weisen Sie
Student.prototype
zuObject.create(Person.prototype)
,Student.prototype
sich dann die DelegiertenPerson.prototype
, und auf der Suche nacheve.species
zurückhuman
als wir erwarten. Vermutlich würden wir wollen, dass es Erben von Studenten.Prototyp UND Person.der Prototyp. Also müssen wir alle zu beheben.Nun die delegation funktioniert, aber wir sind zu überschreiben
Student.prototype
mit derPerson.prototype
. Wenn wir also rufenStudent.prototype.constructor
es würde Punkt-zu -Person
stattStudent
. Diese ist, warum wir brauchen, um es zu beheben.In ES5, unsere
constructor
Eigenschaft ist eine Referenz auf eine Funktion, die wir geschrieben haben, mit der Absicht, ein 'Konstruktor'. Abgesehen von dem, was dienew
Schlüsselwort gibt uns der Konstruktor ist, ansonsten eine 'plain' - Funktion.In ES6, die
constructor
jetzt gebaut wird, in der Art wie wir schreiben-Klassen - wie in, es ist als eine Methode, wenn wir deklarieren eine Klasse. Das ist einfach nur syntaktischer Zucker, aber es tut accord uns einige Annehmlichkeiten, wie den Zugang zu einemsuper
wenn wir die Erweiterung einer vorhandenen Klasse. So würden wir schreiben die obige code wie folgt:eve instanceof Student
zurückgegebentrue
. Siehe stackoverflow.com/questions/35537995/... für die Erklärung. Auch wenn Sie sagenwhich is, at the moment, nothing
was beziehen Sie sich? Jede Funktion hat eine prototype-also, wenn ich überprüfenStudent.prototype
es ist etwas.Mein Fehler. Es sollte gelesen haben "Eva instanceof Person", die den Wert false zurück. Ich werde ergänzen, dass ein Teil. Sie sind richtig, dass jede Funktion hat eine prototype-Eigenschaft. Aber, ohne dass der Prototyp zu
Object.create(Person.prototype)
, dieStudent.prototype
leer ist. Wenn wir also logeve.species
es wird nicht delegieren ordnungsgemäß bis zu Ihrer übergeordneten Klasse Person, und er wird sich nicht melden'human'
. Vermutlich, wir wollen, dass jede Unterklasse erbt von seinem Prototyp, und auch seine super-Prototyp.Um zu klären, durch
which is, at the moment, nothing
, ich meinte, dass dieStudent.prototype
- Objekt leer ist.Mehr über das Vorbild: Ohne die Zuordnung von
Student.prototype
zuObject.create(Person.prototype)
- was ist, wenn Sie sich erinnern, die gleiche Weise alle Instanzen von Person eingerichtet sind, zu delegieren, zuPerson.prototype
- nachschlagen einer Eigenschaft auf eine Instanz vonStudent
würde Stellvertretung nurStudent.prototype
. Soeve.species
nicht seine Suche. Wenn wir das tun, weisen Sie esStudent.prototype
sich dann die DelegiertenPerson.prototype
, und auf der Suche nacheve.species
zurückhuman
.Es scheint, es gibt durchaus ein paar Dinge, die hier falsch: "Es ist notwendig, wenn Sie versuchen zu emulieren 'Unterklassen' [ ... ], so dass, wenn Sie überprüfen, ob eine Instanz ist
instance
die 'Unterklasse' Konstruktor, es wird richtig sein." NÖ,instanceof
nichtconstructor
. "Allerdings, wenn wir uns die Schüler .der Prototyp.Konstruktor, wäre es immer noch Punkt-zu-Person" NÖ, wird esStudent
. Ich verstehe nicht den Punkt von diesem Beispiel. Aufrufen einer Funktion in einem Konstruktor ist nicht Erbe. "In ES6, der Konstruktor wird nun eine tatsächliche Funktion, anstatt eine Referenz auf eine Funktion" Äh, was?InformationsquelleAutor bthehuman
Ich würde nicht Zustimmen. Es ist nicht notwendig, um den Prototyp. Nehmen Sie die exakt gleiche code, aber entfernen Sie der Prototyp.Konstruktor Linie. Tut etwas ändern? Nein. Nun, nehmen Sie die folgenden änderungen:
und am Ende der test-code...
Wird die Farbe blau sein.
Einer änderung der Prototypen.Konstruktor, meiner Erfahrung nach, nicht viel tun, es sei denn, du machst das sehr bestimmte, sehr komplizierte Dinge, die wahrscheinlich nicht eine gute Praxis in jedem Fall 🙂
Bearbeiten:
Nach herumstöbern im web ein wenig und machen einige Experimente, wie es aussieht, die Menschen setzen Sie den Konstruktor so, dass es 'aussieht' wie die Sache, die aufgebaut ist mit einer 'neuen'. Ich denke, ich würde behaupten, dass das problem mit diesem ist, dass javascript ist eine Prototyp-Sprache - es gibt keine solche Sache wie inheritence. Aber die meisten Programmierer kommen aus einem hintergrund, der Programmierung, der schiebt inheritence als "der Weg". Also wir kommen mit allen möglichen Dinge zu versuchen und machen diese prototypische Sprache eine "klassische" Sprache.. wie die Erweiterung der 'Klassen'. Wirklich, in dem Beispiel, das Sie Gaben, eine neue student ist eine person - es ist nicht die "Ausweitung" von einem anderen Studenten.. die Schüler alles über die person, und unabhängig von der person ist der Schüler als gut ist. Erweitern der student, was auch immer Sie haben extended ist ein Schüler am Herzen, sondern wird individuell auf Ihre Bedürfnisse anpassen.
Crockford ist ein bisschen verrückt und übereifrig, aber tun einige ernsthafte Lektüre auf einige der Sachen, die er geschrieben.. werde es machen, Sie schauen sich diese Sachen ganz anders.
clap willkommen im Gespräch, vier Jahre später. Ja, der Prototyp-Kette ist geerbt, unabhängig davon, ob Sie überschreiben den Prototyp.Konstruktor. Testen Sie es aus.
Sie fehlt der code, erbt der Prototyp. Herzlich willkommen auf der internet.
Code-snippet wurde auf der Grundlage der code in dem verlinkten Artikel. Willkommen zum Lesen der Frage in Ihrer Gesamtheit. Oh. Warten.
Ich meinte es wie die klassische Vererbung. Schlechte Wortwahl meinerseits.
InformationsquelleAutor Stephen
Dies ist die große Gefahr, dass, wenn Sie schrieb
aber dann, wenn es einen Lehrer, dessen Prototyp war auch Mensch, und Sie schrieb
dann die Student-Konstruktor ist jetzt Lehrer!
Bearbeiten:
Sie können dies vermeiden, indem Sie sicherstellen, dass Sie gesetzt hatten, die Schüler und Lehrer Prototypen mit neuen Instanzen von der Klasse "Person" erstellt mit dem Objekt.erstellen Sie, wie in der Mozilla-Beispiel.
Student.prototype = Object.create(...)
ist davon ausgegangen, in dieser Frage. Diese Antwort nichts hinzufügt, sondern Verwirrung.Ich fand diese Antwort hilfreich.
Object.create(...)
ist in der MDN-Artikel gespawnt ist die Frage, aber nicht in der Frage selbst. Ich bin sicher, dass viele Leute nicht klicken Sie sich durch.diese Antwort verdient vermutlich mehr upvotes 🙂
Die verlinkten Artikel verwiesen, die in der Frage alreay verwendet Objekt.create(). Diese Antwort und die Edit-ot die Antwort nicht wirklich relevant, und es ist verwirrend:-)
Der breitere Punkt ist, dass es gibt Fallstricke, Haken Menschen neue Javascript-Prototypen. Wenn wir diskutieren im Jahr 2016, dann sollten Sie wirklich verwenden ES6-Klassen, Babel, und/oder Typoskript. Aber wenn Sie wirklich wollen, manuell zu konstruieren, Klassen auf diese Weise, es hilft zu verstehen, wie Prototypen-Ketten wirklich Arbeit zu nutzen, Ihre macht. Können Sie jedes beliebige Objekt als Prototyp und vielleicht haben Sie nicht wollen, um neue ein separates Objekt. Darüber hinaus zurück, bevor HTML 5 voll war weit verbreitet, Objekt.erstellen war nicht immer verfügbar, so war es einfacher einzurichten ist eine Klasse falsch.
InformationsquelleAutor James D
So weit die Verwirrung ist immer noch da.
Folgenden das Beispiel, wie Sie ein vorhandenes Objekt
student1
:Angenommen, Sie möchten nicht wissen, wie
student1
erstellt wird, Sie wollen einfach nur ein anderes Objekt, wie Sie es verwenden, können Sie die constructor-Eigenschaft vonstudent1
wie:Hier, es werden nicht die Eigenschaften von
Student
wenn die constructor-Eigenschaft ist nicht festgelegt. Eher wird es einePerson
Objekt.InformationsquelleAutor Mahavir
Habe einen schönen code-Beispiel dafür, warum es wirklich notwendig ist, um die Prototyp-Konstruktor..
createNewCar
Methode ist die Schaffung von Fabriken!? Auch dieses sieht wie es hätte sein sollen, alsvar audiFactory = new CarFactory("Audi")
anstatt Vererbung.Dein Beispiel mit
this.constructor
intern, so ist es nicht verwunderlich, muss diese noch eingestellt werden. Haben Sie irgendwelche Beispiel ohne?InformationsquelleAutor user3877965
Keine Notwendigkeit für gezuckerte Funktion 'Klassen' oder 'Neue' in diesen Tagen. Verwenden Sie Objekt-Literale.
Die Objekt-Prototyp-ist schon eine 'Klasse'. Wenn Sie definieren, ein Objekt-literal, es wird bereits eine Instanz des Prototyp-Objekt. Diese können auch als ein anderes Objekt, Prototyp, etc.
Dies ist Wert, gelesen zu werden:
InformationsquelleAutor ucsarge
BEARBEITEN, ich war tatsächlich falsch. Kommentieren Sie die Zeile aus, nicht verändern, es ist Verhalten überhaupt. (Habe es getestet)
Ja, es ist nötig. Wenn Sie das tun
Student.prototype.constructor
wirdPerson
. Daher ruftStudent()
zurückkehren würde, ein Objekt erstellt, indemPerson
. Wenn Sie dann tunStudent.prototype.constructor
ist wieder aufStudent
. Wenn Sie jetzt anrufenStudent()
es führtStudent
fordert die übergeordneten KonstruktorParent()
es gibt die richtig geerbte Objekt. Wenn Sie nicht zurücksetzenStudent.prototype.constructor
vor dem Aufruf die Sie erhalten würden, ein Objekt, das keine der Eigenschaften imStudent()
.InformationsquelleAutor invisible bob
Gegeben, einem einfachen Konstruktor-Funktion:
Standardmäßig (von der Spezifikation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor), alle Prototypen erhalten Sie automatisch eine Eigenschaft namens constructor, die Punkte zurück zu der Funktion, auf die es eine Eigenschaft.
Je nach Konstruktor Eigenschaften und Methoden Hinzugefügt werden kann der Prototyp ist nicht sehr üblich, aber noch ist es erlaubt für Erweiterungen.
So einfach zu beantworten: wir müssen sicherstellen, dass der Wert im Prototyp.Konstruktor ist richtig eingestellt, wie es soll, die von der Spezifikation zu sein.
Haben wir immer richtig eingestellt ist dieser Wert? Es hilft bei der Fehlersuche und macht die innere Struktur konsequent gegen die Spezifikation. Wir sollten auf jeden Fall, wenn unsere API verwendet wird, indem die Dritter frei, aber nicht wirklich, wenn der code ist schließlich ausgeführt, die in der Laufzeit.
InformationsquelleAutor kospiotr
Hier ist ein Beispiel von MDN, das fand ich sehr hilfreich, um zu verstehen, verwendet.
In JavaScript haben wir
async-Funktionen
gibt AsyncFunction Objekt.AsyncFunction
ist nicht eine Globale Objekt-man kann Sie aber abrufen, indem mithilfeconstructor
Eigenschaft und verwenden Sie es.InformationsquelleAutor Hitesh Kumar
Ist es nicht notwendig. Es ist nur eines der vielen Dinge, die traditionelle, OOP champions tun, um zu versuchen, schalten Sie JavaScript die prototypische Vererbung in der klassischen Vererbung. Das einzige, was die folgenden
macht, ist, dass Sie haben nun eine Referenz des aktuellen "Konstruktor".
In Wayne ' s Antwort wurde als korrekt markiert, man konnte die genaue gleichen Sache, dass der folgende code tut
mit dem code unten (nur diese ersetzen.Konstruktor mit Person)
Danke Gott, dass mit ES6 klassische Vererbung Puristen kann die Sprache der einheimischen Operatoren wie class, extends und super und wir nicht haben, um zu sehen, wie der Prototyp.Konstruktor Korrekturen und Eltern refereces.
InformationsquelleAutor Roumelis George