Чи можна не оголошувати constructor
Так, конструктор у класі можна не оголошувати: JavaScript автоматично створює його за замовчуванням. Форма цього неявного конструктора залежить від того, чи успадковує клас інший клас через extends.
Теорія
TL;DR
- Якщо
constructor()не написано, рушій додає його сам. - Клас без
extendsотримує порожній конструктор, який нічого не робить. - Клас з
extendsотримуєconstructor(...args) { super(...args); }, тобто прозоро передає аргументи батькові. - Власний конструктор потрібен, коли є нові поля або логіка ініціалізації.
- У похідному класі власний конструктор зобов'язаний викликати
super()до першого використанняthis.
Швидкий приклад
class User {
greet() {
console.log("Hi!");
}
}
const u = new User();
u.greet(); // Hi!Під капотом рушій створює приблизно такий конструктор:
class User {
constructor(...args) {
super(...args); // тільки якщо є батьківський клас
}
}Клас без успадкування
Якщо клас не має extends, стандартний «порожній» конструктор просто нічого не робить.
class User {}
// рівнозначно:
class User {
constructor() {}
}Обидва записи дають той самий результат: new User() створює порожній об'єкт із прототипом User.prototype. Методи класу при цьому працюють як звичайно, бо вони лежать у прототипі, а не створюються в конструкторі.
Клас, що успадковує інший
Якщо клас успадковує інший через extends, конструктор обов'язковий лише тоді, коли ви хочете додати власну логіку та використати this. Якщо його немає, рушій сам додає конструктор, який викликає super().
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {}
// Еквівалентно:
class Dog extends Animal {
constructor(...args) {
super(...args);
}
}
const dog = new Dog("Rex");
console.log(dog.name); // RexСаме тому new Dog("Rex") коректно заповнює name, хоча в Dog не написано жодного рядка конструктора.
Якщо ви пишете конструктор у нащадку
Тоді ви зобов'язані викликати super() перед використанням this, інакше буде помилка.
class Animal {
constructor(name) {
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
// super() обов'язково першим
super(name);
this.breed = breed;
}
}Якщо не викликати:
constructor(name, breed) {
this.breed = breed; // ReferenceError: Must call super constructor before accessing 'this'
}Причина в тому, що в похідному класі об'єкт this створює саме конструктор батька, тож до виклику super() посилатися просто нема на що.
Коли конструктор потрібен
| Ситуація | Чи потрібен constructor() |
|---|---|
| Клас без успадкування | Не потрібен |
| Клас успадковує інший, але не додає нової поведінки | Не потрібен |
| Клас успадковує і додає власні поля | Потрібен, і треба викликати super() |
| Треба виконати логіку під час створення екземпляра (ініціалізація, перевірка) | Потрібен |
Типові помилки
- Писати порожній
constructor() {}«про всяк випадок»: це рівно те, що рушій зробить і без вас, тільки зайвий шум у коді. - Писати в нащадку
constructor(name) { super(); }і губити аргументи, замістьsuper(name)абоsuper(...args). - Звертатися до
thisабо до полів класу доsuper(): будеReferenceError, а неundefined. - Думати, що без конструктора методи класу перестануть працювати. Методи живуть у прототипі й від конструктора не залежать.
- Оголошувати конструктор у нащадку лише для того, щоб викликати
super(...args): конструктор за замовчуванням робить це сам.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.