Est-il possible d'étendre une classe dans ES6 sans appeler la super
méthode pour appeler la classe parent?
EDIT: La question pourrait être trompeuse. Est-ce la norme que nous devons appeler super()
ou est-ce que je manque quelque chose?
Par exemple:
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();
Quand je n'appelle pas super()
la classe dérivée, j'obtiens un problème de portée ->this is not defined
J'exécute ceci avec iojs --harmony dans la v2.3.0
javascript
class
inheritance
ecmascript-6
xhallix
la source
la source
Réponses:
Les règles pour les classes ES2015 (ES6) se résument essentiellement à:
this
ne peut pas être utilisé tant qu'ilsuper
n'est pas appelé.super
s'ils sont des sous-classes, ou ils doivent renvoyer explicitement un objet pour remplacer celui qui n'a pas été initialisé.Cela se résume à deux sections importantes de la spécification ES2015.
La section 8.1.1.3.4 définit la logique pour décider de ce qu'il
this
y a dans la fonction. La partie importante pour les classes est qu'il est possible d'this
être dans un"uninitialized"
état, et quand dans cet état, une tentative d'utilisationthis
lèvera une exception.La section 9.2.2 ,
[[Construct]]
qui définit le comportement des fonctions appelées vianew
ousuper
. Lors de l'appel d'un constructeur de classe de base,this
est initialisé à l'étape 8 de[[Construct]]
, mais dans tous les autres cas, ilthis
n'est pas initialisé. A la fin de la construction,GetThisBinding
est appelé, donc sisuper
n'a pas encore été appelé (donc initialisationthis
), ou si un objet de remplacement explicite n'a pas été retourné, la dernière ligne de l'appel du constructeur lèvera une exception.la source
super()
?super()
le constructeur?return Object.create(new.target.prototype, …)
pour éviter d'appeler le super constructeur.Il y a eu plusieurs réponses et commentaires indiquant que
super
DOIT être la première ligne à l'intérieurconstructor
. C'est tout simplement faux. @loganfsmyth answer a les références requises des exigences, mais cela se résume à:Le
extends
constructeur Inheriting ( ) doit appelersuper
avant d'utiliserthis
et avant de retourner même s'ilthis
n'est pas utiliséVoir le fragment ci-dessous (fonctionne dans Chrome ...) pour voir pourquoi il peut être judicieux d'avoir des instructions (sans utiliser
this
) avant d'appelersuper
.la source
"See fragment below (works in Chrome...)"
ouvrir la console développeur de chrome et cliquez sur « Exécuter extrait de code »:Uncaught ReferenceError: this is not defined
. Bien sûr, vous pouvez utiliser des méthodes dans le constructeur avantsuper()
mais vous ne pouvez pas utiliser des méthodes de la classe avant!this
auparavantsuper()
(votre code le prouve) n'a rien à voir avec la spécification immédiatement, mais avec l'implémentation de javascript. Donc, vous devez appeler «super» avant «ceci».super
, et vous disiez qu'il est illégal d'utiliserthis
avant d'appelersuper
. Nous avons tous les deux raison, nous ne nous comprenons tout simplement pas :-) (Et cette exception était intentionnelle, pour montrer ce qui n'est pas légal - j'ai même nommé la propriété `` WillFail '')La nouvelle syntaxe de classe es6 n'est qu'une autre notation pour les "anciennes" "classes" es5 avec des prototypes. Par conséquent, vous ne pouvez pas instancier une classe spécifique sans définir son prototype (la classe de base).
C'est comme mettre du fromage sur votre sandwich sans le faire. De plus, vous ne pouvez pas mettre de fromage avant de faire le sandwich, alors ...
... l'utilisation d'un
this
mot-clé avant d'appeler la super classe avecsuper()
n'est pas non plus autorisée.Si vous ne spécifiez pas de constructeur pour une classe de base, la définition suivante est utilisée:
Pour les classes dérivées, le constructeur par défaut suivant est utilisé:
EDIT: trouvé ceci sur
developer.mozilla.org
:La source
la source
this
n'est pas du tout utilisé. 2. JS n'est pas un sandwich, et dans ES5, vous pouvez toujours utiliserthis
, même avant d'appeler toute autre fonction que vous aimez (qui pourrait ou non définir la propriété du supplément)this
aussi?! 2. Ma classe JS représente un sandwich et dans ES6 vous ne pouvez pas toujours l'utiliserthis
. J'essaie juste d'expliquer les classes es6 (avec une métaphore), et personne n'a besoin de tels commentaires destructeurs / inutiles.Je viens de m'inscrire pour publier cette solution car les réponses ici ne me satisfont pas le moins car il existe en fait un moyen simple de contourner cela. Ajustez votre modèle de création de classe pour écraser votre logique dans une sous-méthode tout en n'utilisant que le super constructeur et transmettez-lui les arguments du constructeur.
Comme dans, vous ne créez pas de constructeur dans vos sous-classes en soi, mais faites uniquement référence à une méthode qui est remplacée dans la sous-classe respective.
Cela signifie que vous vous libérez de la fonctionnalité de constructeur qui vous est imposée et que vous vous abstenez d'utiliser une méthode régulière - qui peut être remplacée et n'applique pas super () lorsque vous vous laissez le choix si, où et comment vous voulez appeler super (entièrement facultatif) par exemple:
à votre santé!
la source
Vous pouvez omettre super () dans votre sous-classe, si vous omettez complètement le constructeur dans votre sous-classe. Un constructeur par défaut «caché» sera automatiquement inclus dans votre sous-classe. Cependant, si vous incluez le constructeur dans votre sous-classe, super () doit être appelé dans ce constructeur.
Lisez ceci pour plus d'informations.
la source
La réponse par justyourimage est le moyen le plus simple, mais son exemple est un peu gonflé. Voici la version générique:
Ne prolonge pas le réel
constructor()
, utilise juste le faux_constructor()
pour la logique d'instanciation.Notez que cette solution rend le débogage ennuyeux car vous devez entrer dans une méthode supplémentaire pour chaque instanciation.
la source
Essayer:
Demo
la source
A constructor *can* use the super keyword to call the constructor of a parent class.
je dirais donc d'attendre la sortie de l'ES6Je recommanderais d'utiliser OODK-JS si vous avez l'intention de développer les concepts de POO suivants.
la source
Solution simple: je pense que c'est clair pas besoin d'explication.
la source
@Bergi l'a mentionné
new.target.prototype
, mais je cherchais un exemple concret prouvant que vous pouvez accéderthis
(ou mieux, la référence à l'objet avec lequel le code client créenew
, voir ci-dessous) sans avoir à appelersuper()
du tout.Parler c'est pas cher, montrez-moi le code ... Voici donc un exemple:
Qui produira:
Ainsi, vous pouvez voir que nous créons effectivement un objet de type
B
(la classe enfant) qui est également un objet de typeA
(sa classe parent) et dans lechildMethod()
of childB
nous avonsthis
pointé vers l'objetobj
que nous avons créé dans B'sconstructor
avecObject.create(new.target.prototype)
.Et tout cela sans se soucier
super
du tout.Cela tire parti du fait que dans JS, a
constructor
peut renvoyer un objet complètement différent lorsque le code client construit une nouvelle instance avecnew
.J'espère que cela aide quelqu'un.
la source