Programación
Orientada a
Objetos en
JavaScript
1
Temario:
1. Cambio de paradigma
2. Clases y objetos
3. Encapsulación
4. Composición
5. Herencia
6. Sintaxis
7. Ejemplos
2
Distinta abstracción del mundo: la programación orientada a
objetos se centra en seres, representados por sustantivos
normalmente. Se pasa de utilizar funciones que representan
verbos, a utilizar clases, que representan sustantivos.
POO: Dificultad de modificación y actualización: los datos suelen
Cambio de
ser compartidos por los programas, por lo que cualquier ligera
modificación de los datos podía provocar que otro programa
dejara de funcionar de forma indirecta.
paradigma Dificultad de mantenimiento: la corrección de errores que
existía en ese momento era bastante costosa y difícil de realizar.
Dificultad de reutilización: las funciones/rutinas suelen ser muy
dependientes del contexto en el que se crearon y eso dificulta
reaprovecharlas en nuevos programas.
3
Clase
Es la definición del concepto del mundo real, una plantilla que especifique sus
componentes y lo que puede hacer. Una clase define la forma de un tipo de objeto, los
métodos y propiedades que tiene.
Las clases están compuestas por dos elementos:
▪ Atributos: información que almacena la clase.
▪ Métodos: operaciones que pueden realizarse con la clase.
4
Objeto
Los objetos o instancias son el propio “objeto” del mundo real creados a partir de la
definición de una clase.
Un objeto es una colección de variables y funciones agrupadas de manera estructural. A
las variables definidas dentro de un objeto se las denomina propiedades, y las funciones,
métodos.
5
Encapsulación
La encapsulación en programación
orientada a objetos es un mecanismo
que permite proteger el acceso y uso
no controlados de los atributos y
métodos que componen la clase. La
encapsulación de datos es el pilar
básico de la programación orientada a
objetos.
Los atributos y métodos que componen una clase
pueden ser de dos tipos:
Públicos: los datos son accesibles sin control.
Privados: los datos son accesibles de forma controlada.
6
Encapsulación
Para poder encapsular los atributos lo que se tiene que hacer es definirlos
como privados y generar un método público en la clase para poder acceder
a ellos. De esta forma, únicamente son accesibles de forma directa los
atributos por la clase, mientras que el acceso a los mismos por elementos
externos a la clase se deberá de hacer utilizando dichos métodos públicos
La encapsulación no sólo puede realizarse sobre los atributos de la clase,
también es posible realizarla sobre los métodos, es decir, aquellos
métodos que indiquemos que son privados no podrán ser utilizados por
elementos externos a la clase.
7
La composición en programación
orientada a objetos nos va a permitir
utilizar otras clases como atributos de
otras clases. La composición permite
reutilizar código fuente
Composición
Cuando hablemos de composición tienes
que pensar que entre las dos clases existe
una relación del tipo “tiene un”..
8
Herencia
La herencia consiste en la definición de una clase utilizando como base o
plantilla una clase ya existente. La nueva clase derivada tendrá todas las
características de la clase base y ampliará el concepto de ésta, es decir,
tendrá todos los atributos y métodos de la clase base además de los propios
que definas dentro de la misma.
9
class: palabra reservada para definir clases en JavaScript.
NombreClase: indica el nombre de la clase.
constructor: palabra reservada para definir el método constructor de la
clase. El constructor es el método que se ejecutará cada vez que crees un
objeto de la clase.
ParámetrosConstructor: conjunto de parámetros que tiene el
constructor. Los parámetros son opcionales, puedes tener desde cero
Definición de una hasta los que necesites.
BloqueCódigoConstructor: código fuente que se ejecuta como parte del
clase
constructor cuando creas un objeto de la clase.
métodoX: indica el nombre del método.
ParámetrosX: conjunto de parámetros que tiene el método. Los
class NombreClase {
parámetros son opcionales, puedes tener desde cero hasta los que
constructor(ParámetrosConstructor) { necesites.
BloqueCódigoConstructor; }
método1(Parámetros1) { BloqueCódigo1; }
BloqueCódigoX: código fuente que ejecuta el método.
método2(Parámetros2) { BloqueCódigo2; }
10
}
Crear objetos de una clase
Variable = new NombreClase(ParámetrosConstructor);
Variable: variable que almacenará el objeto devuelto por parte
de la creación de este.
new: palabra reservada en JavaScript para crear objetos de una
clase.
NombreClase: nombre de la clase de la que se quiere crear el
objeto.
ParámetrosConstructor: conjunto de parámetros que tiene el
constructor de la clase.
11
class Punto
{
constructor(X, Y)
{
this.X = X;
this.Y = Y;
}
mostrarPunto()
{
[Link]("El punto es (%s, %s)", this.X, this.Y);
}
Ejemplo de }
una clase let punto = new Punto(3,3);
mostrarPunto();
simple
12
this: Su valor no es fijo; depende totalmente de cómo y
dónde se llama a la función.
1. En un Método de Objeto
▪ Cuando usas this dentro de una función que es propiedad de un objeto, this apunta al objeto
mismo.
const programador = {
nombre: "Alex",
saludar: function() {
[Link](`Hola, mi nombre es ${[Link]}`);
}
};
[Link]();
13
this: Su valor no es fijo; depende totalmente de cómo y
dónde se llama a la función.
2. En una Función Global
Si llamas a una función normal (no un método) en el navegador, this apunta al objeto
global window.
function dondeEstoy() {
[Link](this);
}
dondeEstoy(); // En el navegador, verás el objeto Window
14
this: Su valor no es fijo; depende totalmente de cómo y
dónde se llama a la función.
3. El peligro de las Arrow Functions (=>)
Aquí es donde muchos fallan. Las funciones de flecha NO tienen su propio this. Ellas "heredan" el this
del lugar donde fueron creadas.
const usuario = {
nombre: "Lucía",
saludarFlecha: () => {
[Link]([Link]);
}
};
[Link](); // ¡Imprime undefined!
// Porque el 'this' de la flecha apunta al objeto global, no a 'usuario'.
15
class Carrito {
constructor(usuario) {
[Link] = usuario; // 'this' guarda el nombre en la instancia
[Link] = []; // 'this' inicializa un arreglo vacío para esta cuenta
}
agregar(nombre, precio) {// Método para añadir productos
[Link]({ nombre, precio });
[Link](`${nombre} añadido al carrito de ${[Link]}`);
}
calcularTotal() {// Método que usa 'this' para calcular el total
let total = 0;
[Link](item => {
total += [Link];
});
return total;
}
mostrarTicket() {// Método que resume la compra
[Link](`--- Ticket para ${[Link]} ---`);
[Link](p => [Link](`- ${[Link]}: $${[Link]}`));
[Link](`Total a pagar: $${[Link]()}`);
}
}
const miCarrito = new Carrito("Alex"); // 1. Usamos 'const' para crear la instancia (la variable no cambiará de
objeto)
[Link]("Teclado Mecánico", 100); // 2. Ejecutamos los métodos
[Link]("Mouse Gamer", 50); // 3. Imprimimos el resultado usando el contexto de 'this'
[Link]();
16
¿Qué está pasando con this exactamente?
▪ En el constructor: Cuando haces new Carrito("Alex"), JavaScript crea un objeto vacío.
this apunta a ese objeto nuevo y le "pega" las propiedades usuario y productos.
▪ En agregar(): [Link] le dice a la computadora: "No busques cualquier variable
llamada productos, busca la que pertenece a este carrito específico".
▪ En mostrarTicket(): Al llamar a [Link](), estamos invocando un método del
mismo objeto desde otro método. Es como decir "yo mismo sé cómo calcular mi
total".
17
Un error común (El "this" perdido)
Si intentas usar una función normal dentro de un forEach o un setTimeout, this puede perderse:
// ESTO DARÍA ERROR O UNDEFINED
[Link](function(p) {
[Link]([Link]); // Aquí 'this' ya no es el carrito, es el contexto global
});
// SOLUCIÓN: Usar Arrow Functions (=>)
[Link]((p) => {
[Link]([Link]); // La flecha "hereda" el 'this' del carrito. ¡Perfecto!
});
18
Métodos que modifican y devuelven
atributos, utilizados en el encapsulamiento.
Los métodos de lectura de atributos (aquellos que devuelven el valor) tienen la siguiente
sintaxis:
get: palabra que se utiliza para indicar que es un
método que devuelve el valor de un atributo.
get Atributo()
{ atributo: nombre que se le da al método.
return [Link]; return: palabra que se utiliza para devolver el valor
} en el método.
[Link]: atributo de la clase que se
devolverá
19
Métodos que modifican y devuelven
atributos, utilizados en el encapsulamiento.
Los métodos de escritura de atributos (aquellos que modifican el valor) tienen la siguiente
sintaxis:
set: palabra que se utiliza para indicar que es
un método que modifica el valor de un atributo.
set Atributo(valor)
{ atributo: nombre que se le da al método.
[Link] = valor;
valor: nuevo valor que se le asignará al
} atributo.
[Link]: atributo de la clase que se
modificará
20
Ejercicio Composición
Teniendo la clase que hemos utilizado (Punto), definiremos una nueva clase llamada
Triangulo, que contendrá tres atributos Punto y un método para mostrar el triángulo por
pantalla utilizando el método de mostrar punto de la clase Punto. El ejercicio consiste
en la creación de tres objetos de la clase Punto y un objeto de la clase Triangulo que
recibirá los tres objetos de la clase Punto como parámetro del constructor de la clase.
El objeto de la clase Triángulo se mostrará utilizando el método MostrarTriangulo. Por
último, modificaremos la información de los puntos para volver amostrar la información
por pantalla y comprobar que ha cambiado.
21
Ejercicio Herencia
El ejercicio consiste en la utilización de una clase que será heredada por otra. La clase que
será heredada será una clase que llamaremos Electrodomestico, que contendrá una serie de
atributos y métodos que pueden ser heredados por otros electrodomésticos más concretos,
como puede ser la clase Lavadora. La clase Lavadora tendrá disponibles los atributos y
métodos de la clase Electrodomestico. El ejercicio consiste en la creación de un objeto
Lavadora y utilizando los métodos de ambas clases (Lavadora y Electrodomestico) rellenar
toda la información y mostrarla por pantalla.
La herencia en JavaScript se define añadiendo a la definición de la clase que va a heredar la
siguiente información en la cabecera: “extends NombreClaseDeLaQueHereda”. Esto indica
que la clase heredará de la clase especificada en extends.
El constructor de la clase que va a heredar, se agrega la sentencia super(). La sentencia lo
que hace es ejecutar el constructor de la clase de la que hereda.
22
Polimorfismo
Es la capacidad de que diferentes objetos respondan al mismo método de maneras
distintas. En JavaScript, al ser un lenguaje con tipado dinámico, el polimorfismo es muy
natural y se basa principalmente en la herencia y la sobrescritura de métodos.
Imagina que tienes diferentes tipos de "Figuras". Todas tienen un método llamado
dibujar(), pero un Círculo se dibuja distinto a un Cuadrado. El polimorfismo te permite
iterar sobre una lista de figuras y decirles a todas "dibújate", sin que te importe qué
forma tienen exactamente.
23
Ejercicio polimorfismo
Ejemplo Práctico: Sistema de Notificaciones
Vamos a crear una clase base y varias clases hijas que cambian el comportamiento del
método enviar().
24