Estoy escribiendo un programa que serializa objetos. Como parte de eso, necesito obtener la clase de una instancia para poder crear una nueva instancia en el futuro. Noté que puedo llamar a fn.constructor u Object.getPrototypeOf(fn).constructor para obtener la clase de la que proviene la instancia. Por ejemplo:
class Foo {} const myFoo = new Foo(); const constructor1 = myFoo.constructor; const constructor2 = Object.getPrototypeOf(myFoo).constructor; En lo anterior, constructor1 y constructor2 parecen ser siempre los mismos a menos que los establezca manualmente en algún otro valor. ¿Hay alguna circunstancia en la que estos valores serían diferentes?
Ya has identificado la circunstancia en la que son diferentes.
Cuando llamas a Object.getPrototypeOf(myFoo).constructor , estás accediendo a la propiedad del constructor de la instancia prototípica de Foo .
Si tiene una instancia de Foo que no tiene un constructor definido directamente, el acceso "pasa a través de" myFoo y accede a Foo.prototype . Entonces, la única vez que los dos difieren es si redefines manualmente la propiedad del constructor en myFoo , como dijiste:
myFoo.constructor = NotFoo En este caso, JavaScript crea una propiedad directamente en la instancia de myFoo , por lo que el acceso a myFoo.constructor nunca "pasa" a Foo.prototype .
El caso interesante es cuando se trata de herencia:
class Foo1 {} class Foo2 extends Foo1{} const myFoo2 = new Foo2() const proto1 = Object.getPrototypeOf(myFoo2) const proto2 = Object.getPrototypeOf(proto1) proto1.constructor // Foo2 proto2.constructor // Foo1¿Hay alguna circunstancia en la que estos valores serían diferentes?
Claro, y no solo aquellos en los que configuró manualmente el objeto .constructor en una instancia.
También existen objetos "normales" con una propiedad .constructor de este tipo, a saber, objetos prototipo como Foo.prototype .
Otro caso son los objetos sin prototipo, como Object.create(null) u Object.prototype , donde una de sus expresiones provoca una excepción pero la otra funciona.
Luego, puede haber casos (interpretados) en los que .constructor es un getter que devuelve diferentes valores cuando se invoca en una instancia en comparación con el objeto prototipo en sí.
Finalmente, no olvide que constructor1 y constructor2 pueden tener el mismo valor, pero no necesariamente funcionan como espera.