Пошук уроків, статей та іншого контенту
Застосуєте super для виклику конструктора й методів батьківського класу під час розширення поведінки.
supersuper — спеціальне ключове слово в JavaScript, яке використовується всередині похідного класу для звернення до батьківського класу.
За допомогою super можна:
викликати конструктор батьківського класу;
викликати метод батьківського класу;
звертатися до статичних методів і властивостей батьківського класу.
Похідний клас створюють за допомогою extends:
class Child extends Parent {
// ...
}У конструкторі похідного класу super() викликає конструктор батьківського класу.
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name, permissions) {
super(name);
this.permissions = permissions;
}
}
const admin = new Admin("Олена", ["users:read", "users:write"]);
console.log(admin.name); // Олена
console.log(admin.permissions); // [ 'users:read', 'users:write' ]У цьому прикладі:
new Admin(...) запускає конструктор Admin.
super(name) викликає конструктор User.
Конструктор User створює властивість name.
Конструктор Admin додає властивість permissions.
Без виклику super() похідний клас не зможе використовувати this.
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name) {
// Помилка: потрібно викликати super() перед використанням this
this.name = name;
}
}Під час створення об’єкта виникне помилка:
ReferenceError: Must call super constructor in derived class before accessing 'this'У super() можна передати будь-які аргументи, які очікує конструктор батьківського класу:
class Product {
constructor(title, price) {
this.title = title;
this.price = price;
}
}
class DigitalProduct extends Product {
constructor(title, price, fileSize) {
super(title, price);
this.fileSize = fileSize;
}
}
const book = new DigitalProduct("JavaScript Basics", 25, "4 MB");
console.log(book.title); // JavaScript Basics
console.log(book.price); // 25
console.log(book.fileSize); // 4 MBПід час створення екземпляра похідного класу спочатку виконується конструктор батьківського класу, а потім — код похідного класу.
class Animal {
constructor(name) {
console.log("Конструктор Animal");
this.name = name;
}
}
class Dog extends Animal {
constructor(name, breed) {
console.log("Початок конструктора Dog");
super(name);
this.breed = breed;
console.log("Кінець конструктора Dog");
}
}
const dog = new Dog("Рекс", "Labrador");
// Початок конструктора Dog
// Конструктор Animal
// Кінець конструктора Dogsuper() не обов’язково має бути першим рядком конструктора. Однак до його виклику не можна звертатися до this.
Можна виконати підготовку аргументів:
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name) {
const normalizedName = name.trim();
super(normalizedName);
}
}
const admin = new Admin(" Олена ");
console.log(admin.name); // ОленаЯкщо похідний клас перевизначає метод, він може викликати його попередню реалізацію через super.methodName().
class Notification {
send(message) {
console.log(`Надсилання повідомлення: ${message}`);
}
}
class EmailNotification extends Notification {
send(message) {
super.send(message);
console.log("Повідомлення надіслано електронною поштою");
}
}
const notification = new EmailNotification();
notification.send("Ваше замовлення підтверджено");Результат:
Надсилання повідомлення: Ваше замовлення підтверджено
Повідомлення надіслано електронною поштоюТакий підхід дає змогу розширити поведінку батьківського класу, а не повністю дублювати її.
Метод похідного класу може використати результат роботи батьківського методу:
class Price {
getValue() {
return 100;
}
}
class DiscountPrice extends Price {
getValue() {
const originalPrice = super.getValue();
return originalPrice * 0.8;
}
}
const price = new DiscountPrice();
console.log(price.getValue()); // 80super працює з thisПід час виклику super.method() метод батьківського класу виконується з поточним об’єктом як this.
class Counter {
constructor() {
this.value = 0;
}
increment() {
this.value += 1;
}
}
class DoubleCounter extends Counter {
increment() {
super.increment();
super.increment();
}
}
const counter = new DoubleCounter();
counter.increment();
console.log(counter.value); // 2Обидва виклики змінюють value того самого об’єкта counter.
Якщо в похідному класі не оголошено власний конструктор, JavaScript створює його автоматично. Такий конструктор приблизно передає всі аргументи до батьківського класу:
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Student extends User {
// Неявно створюється конструктор:
// constructor(...args) {
// super(...args);
// }
}
const student = new Student("Андрій", 20);
console.log(student.name); // Андрій
console.log(student.age); // 20Власний конструктор потрібно оголошувати, коли похідний клас має додаткові властивості або власну логіку ініціалізації.
super зі статичними методамиsuper можна використовувати не лише в екземплярних методах, а й у статичних методах.
Статичний метод належить самому класу, а не його екземплярам:
class Logger {
static createMessage(text) {
return `[LOG] ${text}`;
}
}
class ErrorLogger extends Logger {
static createMessage(text) {
const message = super.createMessage(text);
return `${message} [ERROR]`;
}
}
console.log(ErrorLogger.createMessage("Не вдалося зберегти файл"));
// [LOG] Не вдалося зберегти файл [ERROR]У статичному методі super.createMessage() викликає статичний метод батьківського класу.
super і гетериsuper також може звертатися до гетера батьківського класу:
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
}
class Admin extends User {
get fullName() {
return `Адміністратор: ${super.fullName}`;
}
}
const admin = new Admin("Олена", "Коваль");
console.log(admin.fullName); // Адміністратор: Олена КовальДля властивості-гетера не використовують дужки:
super.fullNameА для методу використовують виклик:
super.getFullName()class Employee {
constructor(name, salary) {
this.name = name;
this.salary = salary;
}
getInfo() {
return `${this.name}: ${this.salary} грн`;
}
increaseSalary(percent) {
this.salary += this.salary * (percent / 100);
}
}
class Manager extends Employee {
constructor(name, salary, teamSize) {
super(name, salary);
this.teamSize = teamSize;
}
getInfo() {
const employeeInfo = super.getInfo();
return `${employeeInfo}, команда: ${this.teamSize} осіб`;
}
increaseSalary(percent) {
// Менеджер отримує додаткові 5 відсотків до стандартного підвищення
super.increaseSalary(percent + 5);
}
}
const manager = new Manager("Ірина", 30000, 6);
console.log(manager.getInfo());
// Ірина: 30000 грн, команда: 6 осіб
manager.increaseSalary(10);
console.log(manager.salary); // 34500
console.log(manager.getInfo());
// Ірина: 34500 грн, команда: 6 осібУ цьому прикладі:
super(name, salary) ініціалізує властивості батьківського класу;
super.getInfo() повторно використовує логіку формування інформації;
super.increaseSalary(...) викликає батьківський метод із додатковим аргументом;
Manager додає власну поведінку, не дублюючи код Employee.
supersuper() доступний лише в конструкторі похідного класуВиклик super() має сенс для класу, який розширює інший клас:
class User {
constructor(name) {
this.name = name;
}
}
class Admin extends User {
constructor(name) {
super(name);
}
}У класі без extends викликати super() не можна.
this до super()class Parent {
constructor() {
this.value = 1;
}
}
class Child extends Parent {
constructor() {
this.value = 2; // Помилка
super();
}
}Правильний порядок:
class Child extends Parent {
constructor() {
super();
this.value = 2;
}
}super не є звичайною змінноюНе можна зберегти super в окрему змінну:
const parent = super; // Синтаксична помилкаsuper має спеціальне значення лише в певних методах класу.
super() у конструкторіclass Admin extends User {
constructor(name) {
this.name = name;
}
}Якщо клас має власний конструктор, він повинен викликати super() до першого звернення до this.
class Child extends Parent {
print() {
super.print;
}
}Такий код лише отримує посилання на метод і не запускає його. Для виклику потрібні дужки:
class Child extends Parent {
print() {
super.print();
}
}Іноді розробник повністю копіює код батьківського методу в похідний клас. Це ускладнює підтримку коду.
Замість цього варто повторно використати батьківську реалізацію:
class Child extends Parent {
method() {
const result = super.method();
return `${result} додаткова поведінка`;
}
}super не з того контекстуsuper можна використовувати в методах класу, конструкторах і статичних методах, але не у звичайній функції, оголошеній окремо від класу:
function test() {
super.method(); // Синтаксична помилка
}super() викликає конструктор батьківського класу.
У похідному конструкторі super() потрібно викликати до використання this.
super.method() викликає метод батьківського класу.
За допомогою super можна розширити поведінку, не дублюючи код.
У статичних методах super звертається до статичних методів батьківського класу.
super працює з поточним об’єктом як із this.
Якщо похідний клас не має власного конструктора, JavaScript створює конструктор із неявним викликом super(...args).