Sintaxis de clases en JavaScript
Las clases en JavaScript ofrecen una sintaxis para programación orientada a objetos más tradicional, con modo estricto y sin necesidad de hoisting.
Introducción a la sintaxis de clases en JavaScript
Una clase es un molde para crear objetos que comparten la misma estructura y comportamiento. En lugar de escribir manualmente el mismo código repetitivo de función constructora más prototipo, describes el objeto una vez y creas todas las instancias que necesitas. Las clases se introdujeron en ECMAScript 2015 (ES6) y se han convertido en la forma estándar de modelar código orientado a objetos en JavaScript.
Este capítulo cubre lo esencial: cómo declarar una clase, qué hace el constructor, cómo añadir métodos, getters/setters y campos públicos, la diferencia entre declaraciones de clase y expresiones de clase, y dos aspectos que confunden a mucha gente: las clases son funciones bajo el capó y no se elevan (hoisting) como las funciones normales.
Definir una clase
Una clase se declara con la palabra clave class, seguida de un nombre y un cuerpo entre llaves:
class MyClass {
// class body
}Por convención, los nombres de clase usan PascalCase (Rectangle, UserAccount). El cuerpo contiene métodos, getters/setters y campos, pero hay que tener en cuenta que, a diferencia de los objetos literales, los miembros no se separan con comas.
El Constructor
El constructor es un método especial que se ejecuta automáticamente cuando creas una instancia con new. Su función es recibir argumentos e inicializar las propiedades del nuevo objeto a través de this:
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}Una clase puede tener como máximo un constructor. Si lo omites, JavaScript proporciona uno vacío automáticamente.
Crear una instancia
Usa la palabra clave new para construir una instancia. new crea un objeto nuevo, lo vincula a this, ejecuta el constructor y devuelve el objeto:
Métodos de clase
Los métodos declarados en el cuerpo se añaden al prototipo de la clase, de modo que todas las instancias comparten una sola copia en lugar de tener la propia. Dentro de un método, this hace referencia a la instancia sobre la que se llamó:
Los métodos de clase son no enumerables, lo que significa que no aparecerán en un bucle for...in ni en Object.keys() — otra diferencia entre las clases y los objetos simples, donde los métodos añadidos sí son enumerables.
Getters y Setters
Un getter te permite exponer un valor calculado como si fuera una propiedad; un setter te permite interceptar una asignación. Antepón get o set a un método:
Los getters y setters son ideales para validación o valores derivados. Consulta Getters y setters de propiedades para una explicación más detallada.
Campos públicos de clase
Puedes declarar e inicializar propiedades de instancia directamente en el cuerpo de la clase, sin escribirlas dentro del constructor. Estos son los campos públicos de clase:
Los campos se asignan a cada instancia (no al prototipo) antes de que se ejecute el cuerpo del constructor. Para los campos que deben ocultarse al código externo, usa campos privados (el prefijo #) — cubiertos en Propiedades y métodos privados y protegidos.
Métodos estáticos
Un método static pertenece a la clase en sí, no a sus instancias. Los miembros estáticos son útiles para utilidades o funciones de fábrica que están relacionadas con la clase pero no necesitan una instancia específica:
Las clases también admiten campos y propiedades static. Para una visión completa, lee Propiedades y métodos estáticos.
Expresiones de clase
Al igual que las funciones, las clases pueden definirse como expresiones y asignarse a una variable. Las expresiones de clase pueden ser anónimas o con nombre:
Esto es útil cuando necesitas crear una clase de forma condicional, pasarla como argumento o devolverla desde una función.
Las clases son funciones bajo el capó
Una clase es en realidad un tipo especial de función. La sintaxis class es en gran medida azúcar sintáctico sobre el antiguo patrón de función constructora más prototipo, con algunas garantías adicionales:
Las garantías adicionales incluyen: el cuerpo siempre se ejecuta en modo estricto, los métodos son no enumerables y un constructor de clase no puede llamarse sin new (hacerlo lanza un TypeError).
Las clases no tienen hoisting
Las declaraciones de función tienen hoisting — puedes llamarlas antes de que aparezcan en el código. Las declaraciones de clase no son utilizables antes de definirlas. Se elevan en nombre únicamente pero permanecen en la "zona muerta temporal", por lo que acceder a una antes de tiempo lanza un ReferenceError:
Siempre declara una clase antes de usarla.
Resumen
Las clases de JavaScript ofrecen al código orientado a objetos una estructura clara y predecible. En este capítulo has visto cómo declarar una clase, escribir un constructor, añadir métodos de prototipo, getters/setters, campos públicos y métodos static, además de las expresiones de clase. Recuerda los dos aspectos clave: una clase es una función bajo el capó cuyo cuerpo se ejecuta en modo estricto y no puede llamarse sin new, y las declaraciones de clase no tienen hoisting.
Desde aquí, los siguientes pasos naturales son extender clases con Herencia de clases, agrupar utilidades compartidas con Propiedades y métodos estáticos y ocultar el estado interno con Propiedades y métodos privados y protegidos.