Към съдържанието
wannacode

Конструктори и 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.

shop.js
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} €`);
Стъпка по стъпка, с думи
  1. new заделя нов обект. Полетата му още са undefined.
  2. Изпълнява се конструкторът. Аргументите се копират в параметрите му.
  3. this.name = name: от параметъра в полето на този обект.
  4. Същото за цената и бройката.
  5. Конструкторът свърши и параметрите изчезват. В coffee отива стрелка към готовия обект.
  6. Обектът излиза от 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 винаги е параметърът (или друга променлива), никога полето.

Пробвай

Намери грешката

Програмата трябва да отпечата „Чай: 3.2 €“. Вместо това печата „undefined: 3.2 €“. На кой ред е грешката?

Избери реда с грешката.

Идеята

А 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);
Отговор

Пробвай

Как се казва конструкторът?

Какво трябва да пише на празното място?

class Book {
  title;
  author;

  (title, author) {
    this.title = title;
    this.author = author;
  }
}

Упражнение

Обекти, създадени цели

Реши задачите в редактора си. Всеки клас получава конструктор с параметри за всички полета.

1. Човек. Клас Person с име и възраст. Създай двама души и отпечатай данните им.

Изход
Мария, 34 г.
Петър, 19 г.

2. Животно. Клас Animal с вид и възраст. Създай котка на 3 и куче на 7 години.

Изход
Вид: котка, възраст: 3
Вид: куче, възраст: 7

3. Танцова стъпка. Клас 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 €.

Тест

Провери се

1. Кога се изпълнява конструкторът?
2. Как се казва конструкторът в JavaScript?
3. Конструкторът е constructor(name, price). Какво става с new Product()?
4. В конструктора пише this.name = name; Кое е this.name?
5. Как класът дава бройка 1, когато при създаването не е подадена?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·