Factory functions en JavaScript

Funciones en JavaScript que se utilizan para generar objetos.

factory-functions-javascript

Cuando trabajamos con JavaScript y necesitamos crear múltiples objetos con una estructura y comportamiento similar, hay varias opciones disponibles: clases, funciones constructoras o lo que se conoce como factory functions.

Una factory function es, simplemente, una función que devuelve un objeto. No utiliza new, no requiere clases y, en muchos casos, permite una mayor expresividad y control sobre el comportamiento del objeto retornado. La idea es encapsular la lógica de construcción del objeto en una función ordinaria:

function crearUsuario(nombre, edad) {
return {
nombre,
edad,
saludar() {
return `Hola, soy ${nombre} y tengo ${edad} años.`;
}
};
}
const usuario1 = crearUsuario('Michael', 30);
console.log(usuario1.saludar()); // "Hola, soy Michael y tengo 30 años."

Este patrón resulta útil cuando queremos evitar las peculiaridades del uso de this en funciones constructoras o clases. Además, permite crear objetos con ciertas propiedades privadas, algo más difícil de conseguir con clases sin usar símbolos como #.

Ventajas frente a clases o constructores

Aunque las clases introducidas en ES6 aportan una sintaxis más familiar a otros lenguajes, no siempre resultan la opción más adecuada. Las factory functions presentan algunas diferencias útiles:

  • No requieren new: Reducen errores comunes relacionados con olvidar instanciar una clase.
  • Permiten composición: Podemos combinar funciones para extender comportamiento sin usar herencia.
  • Soportan encapsulación: Es posible mantener ciertas variables fuera del alcance del objeto retornado.

Por ejemplo, si queremos ocultar una variable interna:

function crearContador() {
let valor = 0;
return {
incrementar() {
valor++;
},
obtener() {
return valor;
}
};
}
const contador = crearContador();
contador.incrementar();
console.log(contador.obtener()); // 1
console.log(contador.valor); // undefined

Aquí valor es completamente inaccesible desde fuera del objeto. Este tipo de encapsulación no es tan directo con clases tradicionales.

Composición con funciones

Otra ventaja práctica es la facilidad para construir objetos a partir de múltiples factory functions. En lugar de herencia, aplicamos composición. Esta estrategia permite reutilizar funciones pequeñas y especializadas.

function conNombre(nombre) {
return {
obtenerNombre() {
return nombre;
}
};
}
function conEdad(edad) {
return {
obtenerEdad() {
return edad;
}
};
}
function crearPersona(nombre, edad) {
return {
...conNombre(nombre),
...conEdad(edad)
};
}
const persona = crearPersona('Michael', 40);
console.log(persona.obtenerNombre()); // "Michael"
console.log(persona.obtenerEdad()); // 40

Este patrón nos ayuda a construir objetos complejos sin necesidad de cadenas de herencia o lógica acoplada.

Casos en los que tiene sentido utilizarlas

No siempre vamos a usar factory functions. Pero hay situaciones donde encajan especialmente bien:

  • Cuando no necesitamos una jerarquía de clases.
  • Si queremos una forma sencilla de encapsular estado.
  • En proyectos funcionales donde preferimos evitar this.
  • Si trabajamos con composición en lugar de herencia.

También conviene señalar que, en algunos casos, el uso excesivo puede afectar al rendimiento —por ejemplo, al definir métodos dentro de la función en vez de en un prototipo compartido—. Es algo a tener en cuenta en contextos de alto volumen de instanciación.

Conclusión

Las factory functions nos ofrecen una forma flexible de construir objetos en JavaScript. No son una alternativa definitiva a las clases ni a los constructores, pero sí una herramienta útil en muchas situaciones. Nos permiten controlar mejor el estado, facilitar la composición y reducir el acoplamiento en el diseño de nuestros objetos.

Como siempre, la clave está en elegir la estrategia más adecuada según las necesidades del proyecto. Y tener a mano más de una opción nos da margen para escribir código más limpio, mantenible y ajustado a cada caso.