Estoy tratando de descubrir cómo funciona realmente super en JavaScript. Tengo una idea, pero no estoy seguro de su exactitud, así que necesito ayuda.
class A { } class B extends A { constructor() { super(); } } class C extends B { constructor() { super(); } } new CEn el código anterior, el operador 'nuevo' crea un objeto y lo vincula al prototipo del constructor C, la propiedad oculta del constructor C 'thisArg' ahora apunta al objeto recién creado
+---------------------+ | function object | +---------------------+ | - code | +---------------------+ | - outerScope | +---------------------+ | - thisArg | +---------------------+ | - [[Prototype]] | +---------------------+ | + prototype | +---------------------+ | + length | +---------------------+ | + name | +---------------------+NB La propiedad oculta thisArg se puede modificar en cada llamada de función, implícitamente (con los operadores de acceso '.' y '[]'), explícitamente (con los métodos .call, .apply, .bind) o con el operador 'nuevo'
La referencia 'this' del entorno léxico apuntará a cualquier propiedad oculta de función a la que esté apuntando thisArg
De vuelta al proceso. El constructor C se ejecuta, luego el super pasa el objeto recién creado al constructor B, la propiedad oculta del constructor B thisArg ahora apunta al objeto recién creado
lo mismo sucede con el constructor B, se ejecuta y el super pasa el objeto recién creado al constructor A donde comienza la construcción
Cuando A termina la construcción, pasa el objeto a B
Luego B agrega más ranuras a la estructura y pasa a C
Finalmente C finaliza la construcción y devuelve el objeto construido.
Entonces, básicamente, ¿el objeto recién creado primero brota de un constructor a otro y luego se filtra?
Así no es como funciona con class . Las partes de su construcción serían casi correctas con la antigua configuración basada en function , pero class funciona de manera ligeramente diferente en este sentido.
Cuando haces new C , el objeto no se crea hasta que se llama al constructor A Esto es lo que sucede:
new llama al método interno [[Construct]] de C con new.target establecido en C .C antes de que se ejecute super() . this es inaccesible en este punto.C llama al [[Construct]] de B (a través super() ) con new.target aún establecido en C .B antes de que se ejecute super() . this todavía está en accesible.B llama al [[Construct]] de A (a través super() ) con new.target aún establecido en C .A es el constructor base, el [[Construct]] de A crea el objeto, configurando su prototipo a partir de la propiedad prototype de new.target (que es C ).A se ejecuta y tiene acceso a this .B después de que se ejecute super() (y tenga acceso a this ).C después de que se ejecute super() (y tenga acceso a this ).A es el resultado de la new expresión.(Me estoy saltando algunos detalles menores arriba para mayor claridad).
Así es como la construcción class asegura que el nuevo objeto se inicialice en orden desde el constructor base ( A ) hasta el primer constructor derivado ( B ) y finalmente el new objetivo ( C ). De esa manera, A tiene acceso al nuevo objeto primero, seguido de B , seguido de C
Más en el enlace de especificación de arriba.