Constructores y this
En resumen: El constructor en JavaScript es el método constructor, que se ejecuta con new y rellena los campos del objeto a través de this.
Problema
Un café de NaN €
Creas un producto, igual que en la lección anterior, y rellenas los campos línea por línea. Se te olvidó una línea:
const coffee = new Product();coffee.name = "Café";coffee.quantity = 2;console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Café: NaN €El café cuesta NaN € (Not a Number, «no es un número»): el precio es undefined, y undefined * 2 no es un número. JavaScript no se queja. Cuantos más campos tiene una clase, más fácil es saltarse uno. Y un producto sin precio ni siquiera debería poder existir.
La idea
Constructor: sin estos datos no hay objeto
Una clase puede decir qué necesita antes de que puedas crear un objeto a partir de ella. Para eso sirve el constructor: un método especial que se ejecuta con new.
class Product { name; price; quantity;
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
const coffee = new Product("Café", 7.50, 2);console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Café: 15 €- El constructor se llama
constructor, en todas las clases. - Sus parámetros son los datos sin los que un producto no puede existir. Los pasas en los paréntesis de
new:new Product("Café", 7.50, 2). - No devuelve nada.
newdevuelve el objeto nuevo.
Ahora el precio se fija en la misma línea que crea el producto, y se ve cuando falta. Pero JavaScript no cuenta los argumentos. Si pasas dos en lugar de tres, el programa se ejecuta, y la cantidad es undefined:
const coffee = new Product("Café", 7.50);undefinedCafé: NaN €Así que el número de argumentos lo tienes que revisar tú. Cómo un constructor puede rechazar un objeto incorrecto lo verás en el módulo «Errores y excepciones».
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity;}
const coffee = new Product("Café", 7.50, 2);console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Paso a paso, en palabras
- new reserva un objeto nuevo. Sus campos todavía son undefined.
- Se ejecuta el constructor. Los argumentos se copian en sus parámetros.
- this.name = name: del parámetro al campo de este objeto.
- Lo mismo para el precio y la cantidad.
- El constructor termina y los parámetros desaparecen. coffee recibe una flecha al objeto terminado.
- El objeto sale de new ya rellenado, así que el precio no es undefined.
La idea
this: el campo de este objeto
Dentro del constructor hay dos cosas que se llaman name: el parámetro y el campo. El nombre solo es el parámetro. Para el campo escribes this.name.
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity;}this es el objeto que se está creando ahora mismo. this.name = name; significa «guarda el parámetro name en el campo name de este objeto».
En JavaScript, this. es obligatorio siempre que tocas un campo. Sin él, name es siempre el parámetro (u otra variable), nunca el campo.
Pruébalo
Encuentra el error
Elige la línea con el error.
name = name; guarda el parámetro en sí mismo. El campo se queda en undefined. Necesitas this.name = name;. JavaScript no da ningún error, así que un error así es difícil de detectar.
La idea
¿Y el new Product() de la lección anterior?
En la lección anterior no había constructor, y new Product() funcionaba: si no escribes un constructor, JavaScript añade uno vacío. En cuanto escribes el tuyo, cada new lo llama.
Pero JavaScript no revisa si se pasan todos los argumentos. new Product() sigue funcionando, y los campos se quedan en undefined:
const empty = new Product();Product { name: undefined, price: undefined, quantity: undefined }console.log de un objeto muestra sus campos. Aquí se ve que ninguno está rellenado. En Java y C# una línea así no compila, pero en JavaScript depende de ti: pasa todos los argumentos.
La idea
Una cantidad por defecto
La mayoría de los productos del carrito van de uno en uno. Escribir 1 cada vez cansa.
En JavaScript una clase puede tener un solo constructor. En lugar de un segundo constructor, el parámetro recibe un valor por defecto: si no pasas una cantidad, es 1.
constructor(name, price, quantity = 1) { this.name = name; this.price = price; this.quantity = quantity;}quantity = 1 significa «si no se pasa una cantidad, usa 1». Pon un parámetro así al final: así puedes simplemente omitirlo al llamar.
Más precisamente, para curiosos
Un segundo constructor en la clase es un error, y el programa ni siquiera arranca:
SyntaxError: A class may only have one constructorLa ventaja de un solo constructor: si mañana añades una comprobación del precio, está en un solo lugar.
Pruébalo
¿Qué constructor?
¿Qué imprimirá el programa?
class Product { name; price; quantity;
constructor(name, price, quantity = 1) { this.name = name; this.price = price; this.quantity = quantity; }}
const bread = new Product("Pan", 1.20);const milk = new Product("Leche", 2.10, 3);console.log(bread.quantity, milk.quantity);new Product("Pan", 1.20) no tiene cantidad, así que quantity toma el valor por defecto 1. Para la leche se pasa la cantidad: 3.Pruébalo
¿Cómo se llama el constructor?
¿Qué va en el hueco?
class Book {
title;
author;
(title, author) {
this.title = title;
this.author = author;
}
}constructor: es el nombre del constructor en todas las clases.Ejercicio
Objetos creados completos
Resuélvelos en tu editor. Cada clase recibe un constructor con parámetros para todos sus campos.
1. Persona. Una clase Person con un nombre y una edad. Crea dos personas e imprime sus datos.
María, 34 añosPablo, 19 años2. Animal. Una clase Animal con una especie y una edad. Crea un gato de 3 años y un perro de 7.
Especie: gato, edad: 3Especie: perro, edad: 73. Paso de baile. Una clase DanceMove con un nombre y una duración en segundos. En la lección «Métodos de instancia», el paso aprenderá a «ejecutarse» solo.
moonwalk: 5 sMás práctica
- Un libro con constructor. Reescribe
Bookde la lección anterior con un constructorconstructor(title, author). ¿Cuántas líneas ahorraste en el código de debajo de la clase? -
Un producto con cantidad por defecto.
Productconquantity = 1, como en la lección. Haz un array[new Product("Pan", 1.20, 2), new Product("Café", 7.50)]e imprime el nombre y la cantidad de cada uno: «Pan x2», «Café x1». - Reserva. Una clase
Bookingcon el nombre del huésped, el número de noches y el precio por noche. Imprime cuánto cuesta la estancia: 3 noches a 85 € son 255 €.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Arrays · Funciones · Parámetros y return · Clases y objetos
- Continúa en: Métodos de instancia · Encapsulamiento · static: lo que comparten todos los objetos · Herencia
- Ejercicios sobre el tema: Clases y objetos