JS: Introducción a la POO
Teoría: Propiedades y métodos estáticos
En una de las lecciones anteriores implementamos un constructor de dinero (Money). Recordemos su interfaz:
La cantidad de dinero y su moneda son parte de un objeto específico, pero ¿qué pasa con las tasas? A continuación se muestra un ejemplo de una posible implementación del constructor:
Con esta definición de clase, cada objeto recién creado obtendrá su propia copia de la información de las tasas de conversión. Técnicamente, este código funciona, pero lógicamente es incorrecto. Las tasas no están relacionadas con un objeto Money específico, sino que determinan el comportamiento de todo el dinero. Imagina que necesitamos agregar más monedas o cambiar las tasas durante la ejecución del programa. Esto es posible si las tasas se calculan dinámicamente, como ocurre en la vida real. Esto significa que todo debería cambiar sin detener el programa. Debido a la vinculación de estos parámetros a cada objeto individualmente, tendríamos que recrear todos los objetos o reiniciar el programa.
Para resolver este problema, se utilizan las funciones constructoras. Cualquier función en JavaScript es un objeto, y cualquier propiedad agregada a la función constructora está disponible en todos sus objetos:
El acceso a la propiedad del constructor es diferente a llamar a las propiedades normales del objeto en sí. Hay dos formas principales de hacerlo. El primero es directamente a través de la función constructora Money.rates. Es la forma más fácil, pero implica duplicar el nombre de la función constructora. El segundo es a través de la propiedad constructor. Esta es una propiedad especial que proporciona acceso directo al constructor desde los objetos. Esta es la forma preferida cuando estamos dentro del objeto:
Con este enfoque, hemos separado las responsabilidades. El objeto Money solo se ocupa de sus propios datos. El constructor se encarga de las cosas comunes. Esto permite cambiar los parámetros de Money de inmediato para todos los objetos:
Podemos ir un paso más allá y actualizar los datos no directamente, sino a través de métodos:
Pero ten cuidado. Todo lo que está en la función constructora se convierte en un estado global. Cualquier cambio se refleja en todos los objetos al mismo tiempo. A veces esto puede ser bueno, como en nuestro caso, pero en otros casos puede llevar a la desincronización de los datos. Especialmente en situaciones en las que los procesos están separados en el tiempo (código asíncrono).
Estática
Esta funcionalidad se implementa utilizando propiedades y métodos estáticos. Así es como se ve:
Los estáticos, al igual que las clases, son solo azúcar sintáctico sobre las funciones. Pero se vuelven populares porque hacen que el código sea más limpio.
Conclusión
Las propiedades estáticas de las clases en JavaScript se utilizan para almacenar datos que no están relacionados con una instancia específica de la clase, sino que se aplican a toda la clase en general. Se declaran dentro de la clase utilizando la palabra clave static o mediante el acceso al constructor de la clase.
Imaginemos que tenemos una clase "Cuadrado". Queremos que cada instancia de esta clase tenga una longitud de lado predeterminada. En este caso, podemos definir una propiedad estática con este valor para que se utilice al crear el objeto.
Lo mismo se aplica a los métodos comunes de la clase. Por ejemplo, en la clase "Cuadrado" podemos definir un método estático para calcular el área del cuadrado, ya que la fórmula para calcular el área de todos los cuadrados es la misma.
Recomendamos utilizar propiedades estáticas de clase cuando los datos o métodos se aplican a toda la clase en lugar de a un objeto específico. Esto puede mejorar la legibilidad y el rendimiento del código, ya que los datos no se duplicarán en cada objeto de la clase.
Idealmente, las propiedades estáticas de clase deben inicializarse al inicio del programa y nunca cambiarse, ya que una propiedad estática, por sus características, es una variable global. Si se almacenan datos temporales y se modifican, es muy fácil crear un código difícil de mantener con muchos errores.