Comment étendre une classe sans avoir à utiliser super dans ES6?

Est-il possible d’étendre une classe dans ES6 sans appeler la méthode super pour appeler la classe parente?

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() sur la classe dérivée, j’obtiens un problème de scope -> this is not defined

Je lance ceci avec iojs –harmony dans la v2.3.0

Les règles pour les classes ES2015 (ES6) se résument à:

  1. Dans un constructeur de classe enfant, this ne peut pas être utilisé tant que super n’est pas appelé.
  2. Les constructeurs de classe ES6 DOIVENT appeler super s’ils sont des sous-classes ou renvoyer explicitement un object 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 this ya dans la fonction. La partie importante pour les classes est qu’il est possible que this soit dans un état "uninitialized" , et que dans cet état, essayer de l’utiliser utilisera une exception.

Section 9.2.2 , [[Construct]] , qui définit le comportement des fonctions appelées via new ou super . Lors de l’appel d’un constructeur de classe de base, this est initialisé à l’étape 8 de [[Construct]] , mais pour tous les autres cas, this n’est pas initialisé. À la fin de la construction, GetThisBinding est appelé, donc si super n’a pas encore été appelé (l’initialisant ainsi) ou si un object de remplacement explicite n’a pas été renvoyé, la dernière ligne de l’appel du constructeur lancera une exception.

Il y a eu plusieurs réponses et commentaires indiquant que super DOIT être la première ligne du constructor . C’est tout simplement faux. @loganfsmyth answer a les références requirejses des exigences, mais cela se résume à:

Le constructeur héritant ( extends ) doit appeler super avant de l’utiliser et avant de revenir, même si this n’est pas utilisé

Voir fragment ci-dessous (fonctionne dans Chrome …) pour voir pourquoi il pourrait être judicieux d’avoir des déclarations (sans utiliser this ) avant d’appeler super .

 'use ssortingct'; var id = 1; function idgen() { return 'ID:' + id++; } class Base { constructor(id) { this.id = id; } toSsortingng() { return JSON.ssortingngify(this); } } class Derived1 extends Base { constructor() { var anID = idgen() + ':Derived1'; super(anID); this.derivedProp = this.baseProp * 2; } } alert(new Derived1()); 

La nouvelle syntaxe de la classe es6 est seulement une autre notation pour les “anciennes” es5 “classes” 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. Aussi, vous ne pouvez pas mettre du fromage avant de faire le sandwich, alors …

… l’utilisation de this mot this clé avant d’appeler la super-classe avec super() n’est pas autorisée non plus.

 // valid: Add cheese after making the sandwich class CheeseSandwich extend Sandwich { constructor() { super(); this.supplement = "Cheese"; } } // invalid: Add cheese before making sandwich class CheeseSandwich extend Sandwich { constructor() { this.supplement = "Cheese"; super(); } } // invalid: Add cheese without making sandwich class CheeseSandwich extend Sandwich { constructor() { this.supplement = "Cheese"; } } 

Si vous ne spécifiez pas de constructeur pour une classe de base, la définition suivante est utilisée:

 constructor() {} 

Pour les classes dérivées, le constructeur par défaut suivant est utilisé:

 constructor(...args) { super(...args); } 

EDIT: Trouvé sur developer.mozilla.org :

 When used in a constructor, the super keyword appears alone and must be used before the this keyword can be used. 

La source

Juste enregistré pour poster 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 remplacer votre logique dans une sous-méthode en utilisant uniquement le super constructeur et transférez les arguments du constructeur.

Comme dans vous ne créez pas un constructeur dans vos sous-classes en soi mais uniquement une 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é constructeur imposée sur vous et que vous vous abstenez d’utiliser une méthode normale – qui peut être remplacée et ne pas appliquer super () lorsque vous vous décidez si, où et comment vous voulez appeler super facultatif) par exemple:

 super.ObjectConstructor(...) 
 class Observable { constructor() { return this.ObjectConstructor(arguments); } ObjectConstructor(defaultValue, options) { this.obj = { type: "Observable" }; console.log("Observable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } class ArrayObservable extends Observable { ObjectConstructor(defaultValue, options, someMoreOptions) { this.obj = { type: "ArrayObservable" }; console.log("ArrayObservable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } class DomainObservable extends ArrayObservable { ObjectConstructor(defaultValue, domainName, options, dependent1, dependent2) { this.obj = super.ObjectConstructor(defaultValue, options); console.log("DomainObservable ObjectConstructor called with arguments: ", arguments); console.log("obj is:", this.obj); return this.obj; } } var myBasicObservable = new Observable("Basic Value", "Basic Options"); var myArrayObservable = new ArrayObservable("Array Value", "Array Options", "Some More Array Options"); var myDomainObservable = new DomainObservable("Domain Value", "Domain Name", "Domain Options", "Dependency A", "Depenency B"); 

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.

 class A{ constructor(){ this.name = 'hello'; } } class B extends A{ constructor(){ // console.log(this.name); // ReferenceError super(); console.log(this.name); } } class C extends B{} // see? no super(). no constructor() var x = new B; // hello var y = new C; // hello 

Lisez ceci pour plus d’informations.

Je recommande d’utiliser OODK-JS si vous avez l’intention de développer les concepts suivants de la POO.

 OODK(function($, _){ var Character = $.class(function ($, µ, _){ $.public(function __initialize(){ $.log('invoke character'); }); }); var Hero = $.extends(Character).class(function ($, µ, _){ $.public(function __initialize(){ $.super.__initialize(); $.log('invoke hero'); }); }); var hero = $.new(Hero); }); 

Essayer:

 class Character { constructor(){ if(Object.getPrototypeOf(this) === Character.prototype){ console.log('invoke character'); } } } class Hero extends Character{ constructor(){ super(); // throws exception when not called console.log('invoke hero'); } } var hero = new Hero(); console.log('now let\'s invoke Character'); var char = new Character(); 

Démo

Solution simple: je pense que son explication n’est pas évidente.

 class ParentClass() { constructor(skipConstructor = false) { // default value is false if(skipConstructor) return; // code here only gets executed when 'super()' is called with false } } class SubClass extends ParentClass { constructor() { super(true) // true for skipping ParentClass's constructor. // code } }