una tipos identifica herencia example es6 ecmascript cómo clases clase javascript class inheritance ecmascript-6

javascript - tipos - super js



¿Cómo extender una clase sin tener que usar super en ES6? (9)

Acabo de registrarme para publicar esta solución, ya que las respuestas aquí no me satisfacen lo más mínimo, ya que en realidad hay una forma simple de evitar esto. Ajuste su patrón de creación de clase para sobrescribir su lógica en un submétodo mientras usa solo el superconstructor y reenvíele los argumentos del constructor.

Como en el caso, no crea un constructor en sus subclases per se, sino solo una referencia a un método que se anula en la subclase respectiva.

Eso significa que se libera de la funcionalidad del constructor que se le aplica y se abstiene de un método regular , que se puede anular y no impone super () si se permite elegir si, dónde y cómo desea llamar super (totalmente opcional) por ejemplo:

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");

¡salud!

¿Es posible extender una clase en ES6 sin llamar al método super para invocar la clase padre?

EDITAR: La pregunta puede ser engañosa. ¿Es el estándar que tenemos que llamar super() o me falta algo?

Por ejemplo:

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();

Cuando no estoy llamando a super() en la clase derivada, obtengo un problema de alcance -> this is not defined

Estoy ejecutando esto con iojs --harmony en v2.3.0


Ha habido múltiples respuestas y comentarios que indican que super DEBE ser la primera línea dentro del constructor . Eso simplemente está mal. La respuesta @loganfsmyth tiene las referencias requeridas de los requisitos, pero se reduce a:

El constructor heredado (se extends ) debe llamar a super antes de usar this y antes de regresar, incluso si no se usa

Vea el fragmento a continuación (funciona en Chrome ...) para ver por qué podría tener sentido tener declaraciones (sin usar this ) antes de llamar a super .

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


La nueva sintaxis de la clase es6 es solo otra notación para "antiguas" clases "es5" con prototipos. Por lo tanto, no puede crear una instancia de una clase específica sin establecer su prototipo (la clase base).

Eso es como poner queso en tu sándwich sin prepararlo. Tampoco puedes poner queso antes de hacer el sándwich, así que ...

... el uso de this palabra clave antes de llamar a la superclase con super() tampoco está permitido.

// 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 no especifica un constructor para una clase base, se utiliza la siguiente definición:

constructor() {}

Para las clases derivadas, se utiliza el siguiente constructor predeterminado:

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

EDITAR: Encontré esto en developer.mozilla.org :

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

Source


La respuesta de justyourimage es la forma más fácil, pero su ejemplo es un poco hinchado. Aquí está la versión genérica:

class Base { constructor(){ return this._constructor(...arguments); } _constructor(){ // just use this as the constructor, no super() restrictions } } class Ext extends Base { _constructor(){ // _constructor is automatically called, like the real constructor this.is = "easy"; // no need to call super(); } }

No extienda el constructor() real constructor() , solo use el falso _constructor() para la lógica de instanciación.

Tenga en cuenta que esta solución hace que la depuración sea molesta porque tiene que ingresar a un método adicional para cada instanciación.


Las reglas para las clases ES2015 (ES6) básicamente se reducen a:

  1. En un constructor de clase hijo, this no se puede usar hasta que se llame super .
  2. Los constructores de clase ES6 DEBEN llamar a super si son subclases, o deben devolver explícitamente algún objeto para tomar el lugar del que no se inicializó.

Esto se reduce a dos secciones importantes de la especificación ES2015.

La Sección 8.1.1.3.4 define la lógica para decidir qué es this en la función. La parte importante para las clases es que es posible que this esté en un estado "uninitialized" , y cuando esté en este estado, intentar usar this arrojará una excepción.

Sección 9.2.2 , [[Construct]] , que define el comportamiento de las funciones llamadas a través de new o super . Cuando se llama a un constructor de clase base, this se inicializa en el paso 8 de [[Construct]] , pero para todos los demás casos, this no se inicializa. Al final de la construcción, se llama a GetThisBinding , por lo que si todavía no se ha llamado a super (inicializando this ), o no se ha devuelto un objeto de reemplazo explícito, la línea final de la llamada del constructor arrojará una excepción.


Puede omitir super () en su subclase, si omite el constructor por completo en su subclase. Un constructor predeterminado ''oculto'' se incluirá automáticamente en su subclase. Sin embargo, si incluye el constructor en su subclase, se debe llamar a super () en ese constructor.

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

Lea this para más información.


Recomendaría usar OODK-JS si tiene la intención de desarrollar los siguientes conceptos de OOP.

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); });


Solución simple: creo que está claro, no hay necesidad de explicación.

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 } }


Tratar:

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();

Demo