Los miembros estáticos pertenecen a la clase, no a la instancia
La mayoría de los métodos que escribes en una clase operan sobre una instancia concreta: un user en particular, un circle específico. Los métodos estáticos en JavaScript funcionan distinto: pertenecen a la propia clase. Se invocan sobre el nombre de la clase, no sobre una instancia.
double vive en MathUtils, no en sus instancias. Crear una instancia no soluciona nada: m.double es undefined. Es justo lo contrario de los métodos normales, que viven en las instancias (técnicamente, en el prototipo) y resultan invisibles desde la propia clase.
La forma de pensarlo es esta: la palabra clave class crea dos cosas a la vez: un conjunto de métodos de instancia (los que usa new MathUtils()) y un conjunto de métodos estáticos (los que se invocan directamente sobre MathUtils). La palabra clave static decide en qué cajón va cada miembro.
El uso clásico: factory methods
La razón más habitual para escribir un método estático en JavaScript es tener un constructor alternativo. El constructor real recibe los argumentos que recibe, pero muchas veces necesitas otras maneras de crear el objeto: a partir de un JSON, de una fila de base de datos o de una URL.
fromJSON no utiliza un usuario: lo crea. Ese es precisamente el escenario ideal para un método estático. La alternativa sería tener una función suelta parseUser por ahí, pero mantenerla dentro de la clase agrupa el comportamiento relacionado y deja clarísima la intención en el punto donde se llama.
Propiedades estáticas de clase en JavaScript
También puedes asociar datos a la propia clase:
Circle.PI se comparte entre todos los círculos: es una constante de la clase, no una copia que se guarda en cada instancia. Dentro de los métodos de instancia, lo referencias mediante el nombre de la clase (Circle.PI), nunca a través de this.
Las propiedades estáticas de clase en JavaScript resultan muy útiles para configuración, cachés compartidos entre instancias, contadores y constantes a nivel de clase.
this dentro de un método estático es la propia clase
En un método normal, this apunta a la instancia. En un método estático, this apunta a la clase:
this.count dentro de increment equivale a Counter.count. Puede chocar al principio, pero justamente eso es lo que permite que la herencia de métodos estáticos funcione: this apunta a la clase sobre la que llamaste al método, no a la que lo definió.
Herencia de métodos estáticos en JavaScript
Las subclases heredan los métodos estáticos. Y como this apunta a la clase desde la que se invocó el método, los factory methods generan automáticamente la subclase correcta:
Animal.create usa new this(name). Cuando llamas a Dog.create("Rex"), this apunta a Dog, así que new this(name) construye un Dog. Si ahí pusieras new Animal(name), siempre acabarías creando un Animal y romperías el patrón. Esa es justamente la razón principal por la que this, dentro de un método estático, apunta a la clase.
Método static vs instancia en JavaScript: comparación práctica
Mira la misma lógica resuelta con los dos estilos:
Ambos hacen la misma cuenta. La versión de instancia lee datos desde this.celsius. La versión estática recibe su entrada como argumento. Usa el método de instancia cuando la operación sea "algo que este objeto hace"; opta por el método estático cuando se trate de "algo que la clase sabe calcular a partir de ciertas entradas".
Bloques estáticos para la inicialización
A veces inicializar una propiedad estática requiere más que una simple expresión: un bucle, un condicional, varios valores que dependen entre sí. Para eso existen los bloques estáticos (static block):
Un bloque static { ... } se ejecuta una sola vez, cuando se define la clase. Dentro de ese bloque, this hace referencia a la propia clase. Úsalo cuando necesites una inicialización con varios pasos; si solo vas a asignar un valor, un campo estático normal queda mucho más claro.
Miembros estáticos privados en JavaScript
Los campos estáticos también pueden ser privados usando el prefijo #. Así solo se puede acceder a ellos desde dentro de la clase:
#nextId queda encerrado dentro de la clase. Desde fuera se puede llamar a IdGenerator.next(), pero nadie puede tocar ni resetear el contador. A los campos privados les dedicaremos su propia página en breve, pero conviene saber desde ya que la combinación de static con # funciona sin problema.
Cuándo no conviene usar static
Los métodos estáticos son una buena forma de agrupar helpers, pero no son excusa para convertir cualquier utilidad en una clase. Si tienes un archivo con funciones independientes, exporta las funciones y ya está: no las envuelvas en una clase con puros métodos estáticos solo para darles un "namespace". Un módulo ya cumple ese papel, y lo hace de forma más limpia.
Usa static cuando:
- La función realmente pertenece a la clase (un factory method, un conversor o un validador propio de ese tipo).
- Necesitas un estado compartido entre todas las instancias de esa clase.
- Una subclase podría querer heredar o sobrescribir ese comportamiento.
En cualquier otro caso, una función normal es la herramienta más sencilla.
Lo que viene: campos privados
Viste #nextId de pasada: esa es la sintaxis de campos privados de JavaScript. Funciona tanto para miembros de instancia como para estáticos, y es la forma moderna de ocultar detalles de implementación dentro de una clase. Eso es lo que veremos a continuación.
Preguntas frecuentes
¿Qué es un método estático en JavaScript?
Un método estático pertenece a la clase en sí, no a sus instancias. Se declara con la palabra clave static y se llama directamente sobre la clase: MiClase.hacerAlgo(). Las instancias no pueden acceder a él mediante this.hacerAlgo(); solo la clase.
¿Cuándo conviene usar un método estático en lugar de uno de instancia?
Cuando la función está relacionada con la clase pero no necesita leer ni modificar una instancia concreta. Los casos típicos son: métodos factory como User.fromJSON(...), utilidades tipo Math.max y constantes que viven en la clase como si fuera un namespace. Si necesitas que this apunte a una instancia, entonces debe ser un método de instancia.
¿Los métodos estáticos pueden acceder a propiedades de instancia?
No directamente. Dentro de un método estático, this apunta a la clase, no a una instancia, así que this.name lee una propiedad estática, no un campo de instancia. Si necesitas datos de la instancia, pásala como argumento: static summarize(user) { return user.name; }.
¿Se heredan los métodos estáticos en JavaScript?
Sí. Cuando una subclase hace extends de una clase padre, los métodos estáticos del padre también están disponibles en la subclase. Dentro de un método estático, this apunta a la clase desde la que se invocó, y eso es precisamente lo que hace que los métodos factory estáticos funcionen bien con subclases.