Welcome to Our Website

funciones de fábrica de JavaScript vs funciones de Constructor vs clases

antes de ES6, había mucha confusión sobre las diferencias entre una función de fábrica y una función de constructor en JavaScript. Dado que ES6 tiene la palabra clave ‘class’, mucha gente parece pensar que resolvió muchos problemas con las funciones de constructor. Vamos a explorar las principales diferencias que todavía necesita tener en cuenta.,

primero, veamos ejemplos de cada uno:

cada una de estas estrategias almacena métodos en un prototipo compartido, y opcionalmente admite datos privados a través de cierres de función de constructor. En otras palabras, tienen en su mayoría las mismas características, y en su mayoría podrían usarse indistintamente.

En JavaScript, cualquier función puede devolver un objeto nuevo. Cuando no es una función o clase constructora, se llama función de fábrica.,

clases ES6 desugar a funciones de constructor, por lo que todo lo que sigue sobre funciones de constructor también se aplica a las clases ES6:

class Foo {}console.log(typeof Foo); // function

Los Constructores fuerzan a los llamantes a usar la palabra clave new. Las fábricas no. Eso es todo, pero que tiene algunos efectos secundarios.

entonces, ¿qué hace la palabra clave new?,

Nota: usaremosinstancepara hacer referencia a la instancia recién creada, yConstructor para hacer referencia a la función o clase del constructor que creó la instancia.

  1. Crea una instancia de un nuevo objeto de instancia y enlaza this a él dentro del constructor.
  2. se Une instance.__proto__ a Constructor.prototype.
  3. como efecto secundario de 2, se une instance.__proto__.constructora Constructor.,
  4. Implícitamente devuelve this, que se refiere a instance.

beneficios de Los Constructores & `class`

  • La mayoría de los libros le enseñan a usar clase o Constructores.
  • this se refiere al nuevo objeto.
  • a algunas personas les gusta la forma en que myFoo = new Foo() lee.
  • Puede haber un beneficio de rendimiento de microoptimización, pero no debe preocuparse por eso a menos que haya perfilado su código y demostrado que es un problema para usted.,

inconvenientes de Los Constructores & `class`

antes de ES6, olvidar new era un error muy común. Para contrarrestarlo, muchas personas usaron boilerplate para forzarlo:

function Foo() {
if (!(this instanceof Foo)) { return new Foo(); }
}

en ES6 + (ES2015) si intentas llamar a un constructor de clase sin new, siempre lanzará un error. No es posible evitar forzar el requisito new en las personas que llaman sin envolver su clase en una función de fábrica.,

los detalles de la instanciación se filtran en la API de llamada (a través del requisito `Nuevo`).

todas las llamadas están estrechamente acopladas a la implementación del constructor. Si alguna vez necesita la flexibilidad adicional de la fábrica, el refactor es un cambio radical. Los refactores de clase a fábrica son lo suficientemente comunes como para aparecer en el libro de refactorización «Refactoring: Improving the Design of Existing Code» DE Martin Fowler, Kent Beck, John Brant, William Opdyke y Don Roberts.,

Los Constructores rompen el principio Abierto / Cerrado

debido al requisito new, las funciones del constructor violan el principio abierto/cerrado: una API debe estar abierta para la extensión, pero cerrada para la modificación.

sostengo que el Refactor de clase a fábrica es lo suficientemente común como para que se considere una extensión estándar para todos los constructores: actualizar de una clase a una fábrica no debe romper cosas, pero en JavaScript, lo hace.,

si comienza a exportar un constructor o clase y los usuarios comienzan a usar el constructor, luego se dará cuenta de que necesita la flexibilidad de una fábrica (por ejemplo, para cambiar la implementación para usar grupos de objetos, o para crear instancias entre contextos de ejecución, o para tener más flexibilidad de herencia usando prototipos alternativos), no puede hacerlo fácilmente sin forzar un refactor en los llamantes.,

desafortunadamente, en JavaScript, cambiar de un constructor o clase a una fábrica es un cambio radical:

en el ejemplo anterior, comenzamos con una clase, pero queremos agregar la capacidad de ofrecer diferentes tipos de paquetes de automóviles. Para ello, la fábrica utiliza prototipos alternativos para diferentes paquetes de automóviles. He utilizado esta técnica para almacenar varias implementaciones de una interfaz de reproductor multimedia, eligiendo el prototipo correcto basado en el tipo de medio que el reproductor necesitaba controlar.,

el uso de Constructores habilita la ‘instanceof’ engañosa

uno de los cambios de ruptura en el constructor a refactor de fábrica es instanceof. A veces las personas se sienten tentadas a usar instanceof como un tipo de check guard en su código. Eso puede ser muy problemático. Le recomiendo que evite instanceof.

` instanceof ‘ lies.,

instanceof no hacer la comprobación del tipo de la manera que usted espera similar controles a hacer en el establecimiento inflexible de tipos de idiomas. En su lugar, realiza una comprobación de identidad comparando el objeto __proto__ con la propiedad Constructor.prototype.

no funcionará en diferentes reinos de memoria como iframes, por ejemplo (una fuente común de errores en incrustaciones de JavaScript de terceros). Tampoco funciona si tu Constructor.prototype es reemplazado.,

también fallará si comienza con una clase o constructor (que devuelve this, vinculado a Constructor.prototype), y luego cambia a exportar un objeto arbitrario (no vinculado a Constructor.prototype), que es lo que sucede cuando cambia de un constructor a un fábrica.

En resumen, instanceof es otra forma en la que cambiar de un constructor a una fábrica es un cambio radical.

beneficios de usar la clase

  • sintaxis conveniente y autónoma.,
  • Una única forma canónica de emular clases en JavaScript. Antes de ES6, había varias implementaciones competidoras en bibliotecas populares.
  • más familiar para las personas con antecedentes lingüísticos basados en clases.

inconvenientes de usar class

todos los inconvenientes del constructor, además:

  • tentación para los usuarios de crear jerarquías de clase problemáticas usando la palabra clave extends.,

las jerarquías de clase conducen a un montón de problemas bien conocidos en el diseño orientado a objetos, incluyendo el problema de la clase base frágil, el problema del gorila banana, el problema de duplicación por necesidad, y así sucesivamente. Desafortunadamente, la clase se extiende como las bolas permiten lanzar y las sillas permiten sentarse. Para obtener más información, lea «los dos pilares de JavaScript: Prototypal OO» y «dentro de la espiral de muerte del equipo de desarrollo».,

vale la pena señalar que tanto los constructores como las fábricas también se pueden usar para crear jerarquías de herencia problemáticas, pero con la palabra clave `extends`, class crea una asequibilidad que lo lleva por el camino equivocado. En otras palabras, lo alienta a pensar en términos de relaciones inflexibles (y a menudo incorrectas), En lugar de las relaciones compositivas más flexibles que tienen o pueden hacer.

en Una posibilidad es una característica que ofrece la oportunidad de realizar una determinada acción., Por ejemplo, una perilla permite girar, una palanca permite tirar, un botón permite presionar, etc<

los beneficios de usar fábricas

Las fábricas son mucho más flexibles que las funciones de constructor o las clases, y no conducen a las personas por el camino equivocado tentándolas con la palabra clave `extends` y jerarquías de herencia profundas. Hay muchos mecanismos de reutilización de código más seguros que debe favorecer sobre la herencia de clases, incluyendo funciones y módulos.,

devuelve cualquier objeto arbitrario y usa cualquier prototipo arbitrario

por ejemplo, puede crear fácilmente varios tipos de objetos que implementan la misma API, por ejemplo, un reproductor multimedia que puede crear instancias de reproductores para varios tipos de contenido de vídeo que utilizan diferentes API bajo el capó, o una biblioteca de eventos que puede emitir eventos DOM o eventos de socket web.

Las fábricas también pueden crear instancias de objetos en contextos de ejecución, aprovechar los grupos de objetos y permitir modelos de herencia de prototipos más flexibles.,

sin preocupaciones de refactorización

nunca tendría la necesidad de convertir de una fábrica a un constructor, por lo que la refactorización nunca será un problema.

No ‘ new ‘

No hay ambigüedad sobre el uso de new. No. (hará que this se comporte mal, vea el siguiente punto).

el comportamiento estándar `this`

this se comporta como lo haría normalmente, por lo que puede usarlo para acceder al objeto padre. Por ejemplo, dentro de player.create(), this se refiere al jugador, al igual que cualquier otro método de invocación., call() y apply() reasignar this como se esperaba.

a algunas personas les gusta la forma en que `myFoo = createFoo()` lee

  • no crea un enlace desde la instancia aFactory.prototype — pero esto es realmente bueno porque no obtendrá uninstanceof engañoso. En su lugar, instanceof siempre fallará. Ver beneficios.
  • this no se refiere al nuevo objeto dentro de la fábrica. Ver beneficios.,
  • Puede funcionar más lento que una función de constructor en benchmarks de microoptimización. El camino lento sigue siendo muy rápido — millones de ops / seg en un ordenador antiguo. Es más probable que esto sea una preocupación en el código de la biblioteca o del marco que en el código de la aplicación. Siempre benchmark desde la perspectiva del Usuario antes de usar micro-optimizaciones.

conclusión

en mi opinión, class puede tener una sintaxis conveniente, pero eso no puede compensar el hecho de que atrae a los usuarios incautos a estrellarse en las rocas de la herencia de clase., También es arriesgado porque en el futuro, es posible que desee actualizar a una fábrica, pero todas sus llamadas estarán estrechamente acopladas a la función constructor debido a la palabra clave new y el hecho de que pasar de clases a fábricas es un cambio radical.

Puede estar pensando que solo puede refactorizar los sitios de llamadas, pero en equipos grandes, o si la clase con la que está trabajando es parte de una API pública, podría romper el código que no está bajo su control. En otras palabras, no siempre puedes asumir que refactorizar a las personas que llaman es una opción.,

lo bueno de las fábricas es que no solo son más potentes y flexibles, sino que también son la forma más fácil de alentar a equipos enteros y bases de usuarios de API completas a usar patrones que sean simples, flexibles y seguros.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *