Clases y objetos

<< Expresiones regulares Modulos >>

JavaScript es un lenguaje orientado a objetos, y hasta la versión ES2015, trabajar con clases se hacía de una forma bastante diferente a otros lenguajes similares. Sin embargo, esto ha cambiado, y ahora tenemos una sintaxis más familiar para programadores que conocen lenguajes como Java, C#, PHP, etc.

JSON

JSON o JavaScript Object Notation es una notación especial usada para crear objetos genéricos en JavaScript. Es un formato popular para el intercambio de datos entre aplicaciones, o para almacenar información en bases de datos noSQL (MongoDB por ejemplo). Para más información consulta json.org.

Antes de nada, vamos a ver cómo crear un objeto genérico en JavaScript sin usar JSON, y le añadiremos algunas propiedades y métodos (sí, en JavaScript, podemos añadir propiedades y métodos a un objeto en cualquier momento). Para crear un objeto genérico (y por tanto, vacío), usamos la clase Object.

Como podemos ver, añadimos (o accedemos a) propiedades al objeto usando el punto (objeto.propiedad) o la notación de array asociativo (objeto[propiedad]).

Ahora, haremos lo mismo pero usando la notación JSON. Es equivalente a lo que hemos hecho antes, pero lo que haremos será asignarle las propiedades con los dos puntos ':' en lugar del igual '='. Las propiedades iniciales serán declaradas entre llaves, pero podemos añadir más luego como hicimos en el ejemplo anterior. Lo equivalente a usar new Object(), sería dejar las llaves vacías { } (objeto vacío).

En JSON, como en JavaScript, los corchetes se usan para crear arrays. Dentro de un array podemos almacenar otros objetos (en formato JSON siempre), valores primitivos, u otros arrays.

Clases

Desde la versión ES2015 se ha estandarizado una sintaxis más moderna para crear clases en JavaScript, similar a otros lenguajes orientados a objetos, evitando el concepto de funciones constructoras y uso de prototype explícitamente (aunque internamente siga funcionando así)

Para crear un constructor y asignar atributos a los objetos instanciados a partir de la clase, tenemos que implementar un método llamado constructor().

Dentro del constructor y de otros métodos de la clase, debemos usar la palabra reservada this para acceder a las propiedades del objeto actual, ya sea para asignar nuevos valores, o leerlos. Al contrario que en otros lenguajes fuertemente tipados, no necesitamos declarar los atributos del objeto fuera del constructor (aunque se puede hacer), basta con asignarlos.

Así es como declaramos métodos en una clase. Estos métodos tienen acceso al objeto a partir de la referencia this.

Ámbito público/privado

Desde la versión ES2022 se pueden declarar atributos y métodos privados en una clase. Para declararlos como privados, se debe poner una almohadilla '#' delante del nombre del atributo o método en cuestión. De esta manera no podrá ser accedido desde fuera de la clase.

Esto implica que si queremos acceder a atributos privados de un objeto, lo tenemos que hacer mediante métodos (getters/setters), o propiedades públicas. Vamos a ver ambas opciones a continuación. Esto permite controlar el acceso, y por ejemplo, controlar el valor que se le asigna a un atributo, o directamente no permitir el cambio de valor (solo lectura).

Getters/setters estilo Java

Se basa en declarar métodos con el mismo nombre que los atributos y con el prefijo get o set. Llamamos al método en cuestión para acceder o modificar el atributo.

Getters/setters estilo C#/Python

También conocido como propiedades públicas. Internamente funciona igual, pero en este caso el prefijo (get/set) se separa por un espacio. Desde fuera se utiliza como si accedieramos a un atributo público, pero cuando leemos el valor o lo sobrescribimos, por debajo se llama al getter/setter correspondiente. Se podría decir que es una forma más natural de acceder a los atributos de un objeto.

Herencia

Una clase puede heredar de otra utilizando la palabra reservada extends. Heredará todas las propiedades y métodos de la clase padre. Por supuesto, podremos sobrescribirlos en la clase hija, pero seguimos pudiendo llamar a los métodos de la clase padre utilizando la palabra reservada super. De hecho, si creamos un constructor en la clase hija, debemos llamar al constructor padre con super.

Propiedades estáticas

En JavaScript moderno se pueden declarar tanto propiedades como métodos de clase, es decir, independientes de cualquier objeto instanciado. Para ello se pone delante la palabra reservada static. Debemos acceder a dichas propiedades y métodos utilizando el nombre de la clase como prefijo seguida de un punto.

Valor primitivo y string

Cuando un objeto es convertido a string, el método toString (heredado de Object) es automáticamente llamado. Por defecto, imprimirá el texto "[object Object]", pero podemos sobreescribir este método.

Cuando comparamos objetos usando los operadores relacionales (>, <, >=, <=), obtenemos el el valor primitivo por defecto (por defecto toString()). Si sobrescribimos el método valueOf() (heredado de Object), devuelve otro valor primitivo, que será usado para este tipo de comparaciones.

Desestructuración de objetos

Al igual que sucede con los arrays, también es posible desestructurar objetos (extraer parejas propiedad:valor). El funcionamiento es similar a desestructurar un array, pero usamos llaves '{ }' en lugar de corchetes.

Spread de objetos

Podemos utilizar el operador spread '...' con objetos para clonar objetos, o crear nuevos objetos combinando las propiedades de 2 o más objetos. Cuando hay propiedades repetidas en ambos objetos, el valor del último objeto prevalece.

<< Expresiones regulares Modulos >>