Конструктори и this
Проблем
Кафе за NaN €
Създаваш продукт, както в миналия урок, и попълваш полетата ред по ред. Един ред си забравил:
const coffee = new Product();coffee.name = "Кафе";coffee.quantity = 2;console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Кафе: NaN €Кафето струва NaN € (Not a Number, „не е число“): цената е undefined, а undefined * 2 не е число. JavaScript не се оплаква. Колкото повече полета има класът, толкова по-лесно е да пропуснеш едно. А продукт без цена не трябва изобщо да може да съществува.
Идеята
Конструктор: без тези данни няма обект
Класът може да каже какво е нужно, за да се създаде обект от него. За това служи конструкторът: специален метод, който се изпълнява при new.
class Product { name; price; quantity;
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity; }}
const coffee = new Product("Кафе", 7.50, 2);console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Кафе: 15 €- Конструкторът се казва
constructor, във всеки клас. - Параметрите му са данните, без които продукт няма. Те се подават в скобите на
new:new Product("Кафе", 7.50, 2). - Нищо не връща.
newвръща новия обект.
Сега цената се задава на същия ред, на който се създава продуктът, и се вижда, ако липсва. Но JavaScript не брои аргументите. Ако подадеш два вместо три, програмата върви, а бройката е undefined:
const coffee = new Product("Кафе", 7.50);undefinedКафе: NaN €Затова броя на аргументите гледаш сам. Как конструкторът може да откаже лош обект, ще видим в модул „Грешки и изключения“.
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity;}
const coffee = new Product("Кафе", 7.50, 2);console.log(`${coffee.name}: ${coffee.price * coffee.quantity} €`);Стъпка по стъпка, с думи
- new заделя нов обект. Полетата му още са undefined.
- Изпълнява се конструкторът. Аргументите се копират в параметрите му.
- this.name = name: от параметъра в полето на този обект.
- Същото за цената и бройката.
- Конструкторът свърши и параметрите изчезват. В coffee отива стрелка към готовия обект.
- Обектът излиза от new вече попълнен, затова цената не е undefined.
Идеята
this: полето на този обект
Вътре в конструктора има две неща с име name: параметърът и полето. Името без нищо пред него е параметърът. За полето пишеш this.name.
constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity;}this е обектът, който се създава в момента. this.name = name; значи „в полето name на този обект запиши параметъра name“.
В JavaScript this. е задължително, когато пипаш поле. Без него name винаги е параметърът (или друга променлива), никога полето.
Пробвай
Намери грешката
Избери реда с грешката.
name = name; записва параметъра в самия него. Полето остава undefined. Трябва this.name = name;. JavaScript не дава грешка, затова такъв бъг се хваща трудно.
Идеята
А new Product() от миналия урок?
В миналия урок нямаше конструктор, а new Product() работеше: ако не напишеш конструктор, JavaScript добавя празен. Щом напишеш свой, при всяко new се вика той.
Но JavaScript не проверява дали са подадени всички аргументи. new Product() пак работи, а полетата остават undefined:
const empty = new Product();Product { name: undefined, price: undefined, quantity: undefined }console.log на обект показва полетата му. Тук се вижда, че никое не е попълнено. В Java и C# такъв ред не се компилира, а в JavaScript отговорността е твоя: пиши всички аргументи.
Идеята
Бройка по подразбиране
Повечето продукти в количката са по един брой. Да пишеш 1 всеки път е досадно.
В JavaScript класът може да има само един constructor. Вместо втори конструктор параметърът получава стойност по подразбиране: ако не подадеш бройка, тя е 1.
constructor(name, price, quantity = 1) { this.name = name; this.price = price; this.quantity = quantity;}quantity = 1 значи „ако бройка не е подадена, вземи 1“. Сложи такъв параметър последен: тогава при извикването просто го изпускаш.
По-точно, за любопитните
Втори constructor в класа е грешка и програмата изобщо не тръгва:
SyntaxError: A class may only have one constructorПредимството на един конструктор: ако утре добавиш проверка на цената, тя е на едно място.
Пробвай
Кой конструктор?
Какво ще отпечата програмата?
class Product { name; price; quantity;
constructor(name, price, quantity = 1) { this.name = name; this.price = price; this.quantity = quantity; }}
const bread = new Product("Хляб", 1.20);const milk = new Product("Мляко", 2.10, 3);console.log(bread.quantity, milk.quantity);new Product("Хляб", 1.20) няма бройка, затова quantity взима стойността по подразбиране 1. За млякото бройката е подадена: 3.Пробвай
Как се казва конструкторът?
Какво трябва да пише на празното място?
class Book {
title;
author;
(title, author) {
this.title = title;
this.author = author;
}
}constructor: така се казва конструкторът във всеки клас.Упражнение
Обекти, създадени цели
Реши задачите в редактора си. Всеки клас получава конструктор с параметри за всички полета.
1. Човек. Клас Person с име и възраст. Създай двама души и отпечатай данните им.
Мария, 34 г.Петър, 19 г.2. Животно. Клас Animal с вид и възраст. Създай котка на 3 и куче на 7 години.
Вид: котка, възраст: 3Вид: куче, възраст: 73. Танцова стъпка. Клас DanceMove с име и продължителност в секунди. В урока „Поведение“ стъпката ще се научи да се „изпълнява“.
moonwalk: 5 сек.Още задачи
- Книга с конструктор. Препиши
Bookот миналия урок с конструкторconstructor(title, author). Колко реда спести в кода под класа? -
Продукт с бройка по подразбиране.
Productсquantity = 1, както в урока. Направи масив[new Product("Хляб", 1.20, 2), new Product("Кафе", 7.50)]и отпечатай името и бройката на всеки: „Хляб x2“, „Кафе x1“. - Резервация. Клас
Bookingс име на госта, брой нощувки и цена за нощувка. Отпечатай колко струва престоят: за 3 нощувки по 85 € това е 255 €.
Тест