Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Чи можна не оголошувати constructor». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Так, `constructor()` не обов'язковий: якщо ви його не написали, JavaScript додає конструктор за замовчуванням.** Для класу без `extends` це порожній конструктор, який нічого не робить. Для класу з `extends` рушій підставляє `constructor(...args) { super(...args); }`, тобто всі аргументи просто передаються батькові. Писати конструктор вручну треба лише тоді, коли потрібна власна логіка ініціалізації або нові поля, і в похідному класі тоді обов'язково викликати `super()` до першого звернення до `this`. ```javascript class Dog extends Animal {} // те саме, що constructor(...args) { super(...args); } ``` **Ключове:** конструктор за замовчуванням є завжди, ви лише вирішуєте, чи перевизначати його.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Так, конструктор у класі можна не оголошувати: JavaScript автоматично створює його за замовчуванням.** Форма цього неявного конструктора залежить від того, чи успадковує клас інший клас через `extends`. ## Теорія ### TL;DR - Якщо `constructor()` не написано, рушій додає його сам. - Клас без `extends` отримує порожній конструктор, який нічого не робить. - Клас з `extends` отримує `constructor(...args) { super(...args); }`, тобто прозоро передає аргументи батькові. - Власний конструктор потрібен, коли є нові поля або логіка ініціалізації. - У похідному класі власний конструктор зобов'язаний викликати `super()` до першого використання `this`. ### Швидкий приклад ```javascript class User { greet() { console.log("Hi!"); } } const u = new User(); u.greet(); // Hi! ``` Під капотом рушій створює приблизно такий конструктор: ```javascript class User { constructor(...args) { super(...args); // тільки якщо є батьківський клас } } ``` ### Клас без успадкування Якщо клас не має `extends`, стандартний «порожній» конструктор просто нічого не робить. ```javascript class User {} // рівнозначно: class User { constructor() {} } ``` Обидва записи дають той самий результат: `new User()` створює порожній об'єкт із прототипом `User.prototype`. Методи класу при цьому працюють як звичайно, бо вони лежать у прототипі, а не створюються в конструкторі. ### Клас, що успадковує інший Якщо клас успадковує інший через `extends`, конструктор обов'язковий лише тоді, коли ви хочете додати власну логіку та використати `this`. Якщо його немає, рушій сам додає конструктор, який викликає `super()`. ```javascript 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`, інакше буде помилка. ```javascript class Animal { constructor(name) { this.name = name; } } class Dog extends Animal { constructor(name, breed) { // super() обов'язково першим super(name); this.breed = breed; } } ``` Якщо не викликати: ```javascript 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)`: конструктор за замовчуванням робить це сам.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.