Estaba escribiendo código y me encontré con este escenario que no puedo entender.
El escenario es el siguiente: tengo una clase de una biblioteca que estoy ampliando. Esta clase es la clase "Padre". Permite que sus subclases sobrescriban el método init para realizar una inicialización personalizada.
Sin embargo, la segunda clase secundaria no se comporta como yo esperaría. La única diferencia entre ambas clases es la declaración (?) de la variable miembro. Al escribir JS puro, ni siquiera consideraría hacer esto, pero estoy escribiendo en Typescript y este es el resultado compilado (en realidad, ni siquiera estoy asignando un valor en mi caso específico. El compilador TS solo incluye un "miembro; " y la salida dice "indefinido)
Estoy bastante seguro de que este problema solo ocurre cuando la variable se establece en una función sobrescrita a la que llama el constructor principal.
¿Alguien puede explicarme por qué sucede esto?
class Parent { constructor(initArgs) { this.init(initArgs); } init() {} } class ChildTest1 extends Parent { init(args) { this.member = args; } test() { console.log(`Member of ChildTest1 has value of "${this.member}"`); } } class ChildTest2 extends Parent { member = "default"; init(args) { this.member = args; } test() { console.log(`Member of ChildTest2 has value of "${this.member}"`); } } new ChildTest1("Hello World").test(); new ChildTest2("Hello World").test();Produce lo siguiente:
El miembro de ChildTest1 tiene el valor "Hello World"
Miembro de ChildTest2 tiene valor de "predeterminado"
Su variable se sobrescribe durante la inicialización. El orden de inicialización de propiedades y ejecución del constructor es el siguiente:
El constructor de su clase principal ejecuta e inicializa el member en Hello World
Las propiedades de su clase secundaria se inicializan, sobrescribiendo la variable miembro previamente inicializada.
Su constructor de clase hijo se ejecuta
He hecho su código más explícito (tenga en cuenta que agregar el constructor secundario es funcionalmente equivalente a su ejemplo) para demostrar esto:
class Parent { constructor(initArgs) { this.init(initArgs); console.log(`Parent Constructor: Member of ChildTest2 has value of "${this.member}"`); } init() {} } class ChildTest2 extends Parent { member = "default"; constructor(initArgs) { super(initArgs); console.log(`Child Constructor: Member of ChildTest2 has value of "${this.member}"`); } init(args) { this.member = args; console.log(`Init: Member of ChildTest2 has value of "${this.member}"`); } test() { console.log(`Test: Member of ChildTest2 has value of "${this.member}"`); } } new ChildTest2("Hello World").test();Esto imprime:
[LOG]: "Init: Member of ChildTest2 has value of "Hello World"" [LOG]: "Parent Constructor: Member of ChildTest2 has value of "Hello World"" [LOG]: "Child Constructor: Member of ChildTest2 has value of "default"" [LOG]: "Test: Member of ChildTest2 has value of "default"" Como modelo mental, puede suponer que la inicialización de la propiedad de clase ocurre después de la llamada super(...) dentro del constructor. Más sobre eso aquí