Що робить return всередині конструктора?
1. Звичайна поведінка конструктора
Коли ти створюєш екземпляр класу:
class User {
constructor(name) {
this.name = name;
}
}
const u = new User("Alice");JS під капотом робить приблизно таке:
- Створює новий порожній об'єкт
{}. - Встановлює прототип цього об'єкта →
User.prototype. - Викликає
constructorізthis, що посилається на цей новий об'єкт. - Повертає
thisіз конструктора (за умовчанням).
Тобто якщо ти нічого не повертаєш, return this виконується неявно.
2. Що якщо явно використати return?
Якщо return повертає об'єкт, він замінює this
class User {
constructor(name) {
this.name = name;
return { custom: "a different object" };
}
}
const u = new User("Alice");
console.log(u); // { custom: "a different object" }Тобто якщо ти повертаєш об'єкт, він замінює екземпляр, що створюється.
Якщо return повертає примітив (число, рядок, булеве значення тощо)
Примітиви ігноруються, і повертається початковий this.
class User {
constructor(name) {
this.name = name;
return 42;
}
}
const u = new User("Alice");
console.log(u); // User { name: "Alice" }Важливо: конструктор не може «перезаписати» this примітивом.
3. Чому так зроблено
JS дозволяє повертати об'єкт із конструктора, щоб ти міг підмінити екземпляр, якщо потрібно повернути щось особливе.
Приклад: реалізуємо синглтон (один об'єкт для всіх викликів):
class Database {
constructor() {
if (Database.instance) {
return Database.instance; // завжди повертає один об'єкт
}
this.connected = true;
Database.instance = this;
}
}
const a = new Database();
const b = new Database();
console.log(a === b); // trueТут
return thisне потрібен, бо JS робить це сам, алеreturn Database.instanceпідміняє екземпляр, що створюється.
4. Чи можна використовувати return у класах без extends?
Так, можна, поведінка однакова.
Але якщо клас успадковується (extends) і ти повертаєш об'єкт,
він теж замінить this:
class A {}
class B extends A {
constructor() {
super();
return { name: "replacement" };
}
}
const b = new B();
console.log(b); // { name: "replacement" }5. Що буде, якщо не викликати super() у нащадку і спробувати return?
class A {}
class B extends A {
constructor() {
// Помилка, навіть якщо є return
return { test: 1 };
}
}
new B(); // ReferenceError: Must call super constructor before returning from derived constructorУ класах-нащадках super() обов'язковий, навіть якщо ти повертаєш свій об'єкт.
6. Правила в одному місці
| Сценарій | Що повертається |
|---|---|
Немає return | this (створений екземпляр) |
return this | той самий екземпляр |
return { ... } | замість this підставляється цей об'єкт |
return 42 / "hi" / true | ігнорується, повертається this |
Нащадок без super() | Помилка (треба викликати super() до return) |
Приклад для розуміння
class Example {
constructor(x) {
this.x = x;
if (x > 10) return { value: "too large" };
}
}
console.log(new Example(5)); // Example { x: 5 }
console.log(new Example(20)); // { value: "too large" }Якщо
x > 10, повертається "свій" об'єкт, якщо ні, звичайний екземпляр класу.
Підсумок
returnу конструкторі не обов'язковий, за умовчанням повертаєтьсяthis.- Якщо повернути об'єкт, він замінить
this. - Якщо повернути примітив, він ігнорується.
- У класах, що успадковуються,
super()обов'язковий доreturn. - Ця поведінка зручна для таких шаблонів, як Singleton, Factory, Proxy тощо.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.