Ist es möglich, eine Klasse in ES6 zu erweitern, ohne die super
Methode zum Aufrufen der übergeordneten Klasse aufzurufen?
EDIT: Die Frage könnte irreführend sein. Ist es der Standard, den wir anrufen müssen, super()
oder fehlt mir etwas?
Beispielsweise:
class Character {
constructor(){
console.log('invoke character');
}
}
class Hero extends Character{
constructor(){
super(); // exception thrown here when not called
console.log('invoke hero');
}
}
var hero = new Hero();
Wenn ich super()
die abgeleitete Klasse nicht aufrufe, tritt ein Bereichsproblem auf ->this is not defined
Ich führe dies mit iojs --harmony in v2.3.0 aus
javascript
class
inheritance
ecmascript-6
xhallix
quelle
quelle
Antworten:
Die Regeln für ES2015 (ES6) -Klassen lauten im Wesentlichen auf:
this
Kann in einem untergeordneten Klassenkonstruktor erst verwendet werden, wenn ersuper
aufgerufen wird.super
wenn es sich um Unterklassen handelt, oder sie müssen explizit ein Objekt zurückgeben, um den Platz des nicht initialisierten Objekts einzunehmen.Dies ist auf zwei wichtige Abschnitte der ES2015-Spezifikation zurückzuführen.
Abschnitt 8.1.1.3.4 definiert die Logik, um zu entscheiden, was
this
in der Funktion enthalten ist. Der wichtige Teil für Klassen ist, dass es möglich ist,this
sich in einem"uninitialized"
Zustand zu befinden. Wenn Sie sich in diesem Zustand befinden, wird beim Versuch, eine Verwendung zu verwendenthis
, eine Ausnahme ausgelöst.Abschnitt 9.2.2 ,
[[Construct]]
der das Verhalten von Funktionen definiert, die übernew
oder aufgerufen werdensuper
. Wird beim Aufrufen eines Basisklassenkonstruktorsthis
in Schritt 8 von initialisiert, in[[Construct]]
allen anderen Fällenthis
jedoch nicht initialisiert.GetThisBinding
Wird am Ende der Konstruktion aufgerufen. Wenn alsosuper
noch nicht aufgerufen wurde (also initialisiertthis
) oder kein explizites Ersatzobjekt zurückgegeben wurde, löst die letzte Zeile des Konstruktoraufrufs eine Ausnahme aus.quelle
super()
?super()
den Konstruktor aufzurufen ?return Object.create(new.target.prototype, …)
vermeiden, indem Sie den Superkonstruktor aufrufen.Es gab mehrere Antworten und Kommentare, die
super
besagten, dass die erste Zeile darin sein mussconstructor
. Das ist einfach falsch. @loganfsmyth Antwort hat die erforderlichen Referenzen der Anforderungen, aber es läuft auf:Der
extends
Konstruktor Inheriting ( ) musssuper
vor der Verwendungthis
und vor der Rückgabe aufrufen , auch wennthis
nicht verwendet wirdIm folgenden Fragment (funktioniert in Chrome ...) erfahren Sie, warum es möglicherweise sinnvoll ist,
this
vor dem Aufruf Anweisungen (ohne Verwendung ) zu habensuper
.quelle
"See fragment below (works in Chrome...)"
Öffnen Sie die Chrome-Entwicklerkonsole und klicken Sie auf "Code-Snippet ausführen" :Uncaught ReferenceError: this is not defined
. Natürlich können Sie vorher Methoden im Konstruktor verwenden,super()
aber Sie können vorher keine Methoden aus der Klasse verwenden!this
vorher nicht verwenden könnensuper()
(Ihr Code beweist es), hat nichts mit der sofortigen Spezifikation zu tun, sondern mit der Implementierung von Javascript. Also, müssen Sie ‚super‘ nennen , bevor ‚this‘.super
, und Sie haben angegeben, dass die Verwendungthis
vor dem Anruf illegal istsuper
. Wir haben beide Recht, haben uns einfach nicht verstanden :-) (Und diese Ausnahme war beabsichtigt, um zu zeigen, was nicht legal ist - ich habe sogar die Eigenschaft 'WillFail' genannt)Die neue Syntax der es6-Klasse ist nur eine andere Notation für "alte" es5-Klassen mit Prototypen. Daher können Sie eine bestimmte Klasse nicht instanziieren, ohne ihren Prototyp (die Basisklasse) festzulegen.
Das ist so, als würde man Käse auf das Sandwich legen, ohne es zuzubereiten. Sie können auch keinen Käse vor das Sandwich legen , also ...
... die Verwendung eines
this
Schlüsselworts vor dem Aufruf der Superklasse mitsuper()
ist ebenfalls nicht zulässig.Wenn Sie keinen Konstruktor für eine Basisklasse angeben, wird die folgende Definition verwendet:
Für abgeleitete Klassen wird der folgende Standardkonstruktor verwendet:
EDIT: Gefunden am
developer.mozilla.org
:Quelle
quelle
this
nicht verwendet. 2. JS ist kein Sandwich, und in ES5 können Sie es immer verwendenthis
, noch bevor Sie eine andere Funktion aufrufen, die Ihnen gefällt (die möglicherweise die Supplement-Eigenschaft definiert oder nicht)this
?! 2. Meine JS-Klasse stellt ein Sandwich dar, und in ES6 können Sie es nicht immer verwendenthis
. Ich versuche nur, es6-Klassen (mit einer Metapher) zu erklären, und niemand braucht solche destruktiven / unnötigen Kommentare.Ich habe mich gerade registriert, um diese Lösung zu veröffentlichen, da die Antworten hier mich nicht im geringsten befriedigen, da es tatsächlich einen einfachen Weg gibt, dies zu umgehen. Passen Sie Ihr Klassenerstellungsmuster an, um Ihre Logik in einer Untermethode zu überschreiben, während Sie nur den Superkonstruktor verwenden, und leiten Sie die Konstruktorargumente an diese weiter.
Wie in erstellen Sie keinen Konstruktor in Ihren Unterklassen an sich, sondern verweisen nur auf eine Methode, die in der jeweiligen Unterklasse überschrieben wird.
Das bedeutet, dass Sie sich von der Konstruktorfunktionalität befreien, die Ihnen auferlegt wurde, und auf eine reguläre Methode verzichten - die überschrieben werden kann und super () nicht erzwingt, wenn Sie die Wahl haben, ob, wo und wie Sie super (vollständig) aufrufen möchten optional) zB:
Prost!
quelle
Sie können super () in Ihrer Unterklasse weglassen, wenn Sie den Konstruktor in Ihrer Unterklasse ganz weglassen. Ein 'versteckter' Standardkonstruktor wird automatisch in Ihre Unterklasse aufgenommen. Wenn Sie jedoch den Konstruktor in Ihre Unterklasse aufnehmen, muss super () in diesem Konstruktor aufgerufen werden.
Lesen Sie dies für weitere Informationen.
quelle
Die Antwort von justyourimage ist der einfachste Weg, aber sein Beispiel ist ein wenig aufgebläht. Hier ist die generische Version:
Erweitern Sie nicht die reale
constructor()
, verwenden Sie nur die Fälschung_constructor()
für die Instanziierungslogik.Beachten Sie, dass diese Lösung das Debuggen ärgerlich macht, da Sie für jede Instanziierung eine zusätzliche Methode anwenden müssen.
quelle
Versuchen:
Demo
quelle
A constructor *can* use the super keyword to call the constructor of a parent class.
so würde ich sagen , Warten auf ES6 ReleaseIch würde empfehlen, OODK-JS zu verwenden, wenn Sie folgende OOP-Konzepte entwickeln möchten .
quelle
Einfache Lösung: Ich denke, es ist klar, dass es keiner Erklärung bedarf.
quelle
@Bergi erwähnt
new.target.prototype
, aber ich suchte nach einem konkreten Beispiel, das beweist, dass Sie aufthis
(oder besser auf den Verweis auf das Objekt, mit dem der Client-Code erstelltnew
, siehe unten) zugreifen können , ohne überhaupt aufrufensuper()
zu müssen.Sprechen ist billig, zeig mir den Code ... Also hier ein Beispiel:
Welches wird ausgegeben:
So können Sie sehen , dass wir effektiv ein Objekt vom Typ erstellen
B
(das Kind Klasse) , die auch ein Objekt vom Typ istA
(seine Elternklasse) und innerhalb derchildMethod()
von KindB
haben wirthis
auf das Objekt zeigen ,obj
die wir in B erstelltconstructor
mitObject.create(new.target.prototype)
.Und das alles, ohne sich darum
super
zu kümmern .Dies nutzt die Tatsache, dass in JS a
constructor
ein völlig anderes Objekt zurückgegeben werden kann, wenn der Clientcode eine neue Instanz mit erstelltnew
.Hoffe das hilft jemandem.
quelle