Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Ключове слово super». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`super` це посилання на батьківський клас.** У конструкторі нащадка виклик `super(...)` запускає конструктор батька і саме він створює `this`, тому звертатися до `this` можна лише після нього. У звичайних методах `super` вказує на `Parent.prototype`, тож `super.method()` це фактично `Parent.prototype.method.call(this)`, а в статичних методах `super` вказує на сам `Parent`. ```javascript class Dog extends Animal { constructor(name, breed) { super(name); // creates this via the parent constructor this.breed = breed; } } ``` **Ключове:** без `super()` у конструкторі нащадка `this` ще не існує, а поза класом-нащадком `super()` взагалі є синтаксичною помилкою.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`super` дає доступ до батьківського класу зсередини нащадка.** Як виклик, `super(...)`, він запускає конструктор батька і створює `this`; як об'єкт, `super.x`, він читає члени батьківського прототипу або самої батьківської функції. ## Теорія ### TL;DR - `super(name)` у конструкторі викликає конструктор батька і ініціалізує `this`. - До виклику `super()` звертання до `this` кидає `ReferenceError`. - У звичайних методах `super` вказує на `Parent.prototype`, тому `super.method()` дорівнює `Parent.prototype.method.call(this)`. - У статичних методах `super` вказує на сам `Parent`, тобто на його статику. - `super()` дозволений тільки всередині класу з `extends`, інакше це `SyntaxError`. - Стрілкові функції не мають власного `super` і беруть його із зовнішнього контексту класу. ### Швидкий приклад ```javascript class Animal { constructor(name) { this.name = name; } } class Dog extends Animal { constructor(name, breed) { super(name); // calls Animal.constructor(name) this.breed = breed; } } const dog = new Dog("Rex", "shepherd"); console.log(dog.name); // "Rex" console.log(dog.breed); // "shepherd" ``` ### super() у конструкторі: виклик батька Що відбувається під капотом, коли один клас успадковує інший: 1. До виклику `super()` об'єкт `this` ще не існує. 2. Виклик `super(name)` виконує конструктор батька (`Animal`) і створює `this`, який уже можна використовувати. 3. Лише після цього можна присвоювати поля в `this`. Якщо спробувати використати `this` до `super()`, рушій кине помилку: ```javascript class Dog extends Animal { constructor(name) { this.name = name; // ReferenceError super(name); } } ``` > `ReferenceError: Must call super constructor before accessing 'this'` Причина проста: саме `super()` ініціалізує контекст екземпляра. Без нього `this` ще не створено. ### super поза конструктором: методи батька `super` працює не лише в конструкторі, а і в будь-якому методі класу, щоб викликати батьківську реалізацію. ```javascript class Animal { speak() { console.log("The animal makes a sound"); } } class Dog extends Animal { speak() { super.speak(); // calls the parent method console.log("The dog barks"); } } new Dog().speak(); // "The animal makes a sound" // "The dog barks" ``` Так само зручно нарощувати результат батьківського методу замість того, щоб дублювати його код: ```javascript class Animal { constructor(name) { this.name = name; } info() { return `Name: ${this.name}`; } } class Dog extends Animal { constructor(name, breed) { super(name); // calls Animal.constructor() this.breed = breed; } info() { return `${super.info()}, breed: ${this.breed}`; } } const dog = new Dog("Rex", "Beagle"); console.log(dog.info()); // Name: Rex, breed: Beagle ``` ### super у статичних методах Якщо в класу є статичні методи, `super` усередині них звертається до статики батька: ```javascript class Parent { static sayHi() { console.log("Hello from the parent"); } } class Child extends Parent { static sayHi() { super.sayHi(); // calls Parent.sayHi() console.log("Hello from the child"); } } Child.sayHi(); // Hello from the parent // Hello from the child ``` ### На що насправді вказує super Під капотом `super` це посилання на батьківський об'єкт, і цей об'єкт різний залежно від того, де ви пишете `super`: - у звичайних методах `super` вказує на `Parent.prototype`; - у статичних методах `super` вказує на сам `Parent`. Тому виклик: ```javascript super.method() ``` еквівалентний: ```javascript Parent.prototype.method.call(this) ``` Важлива деталь: `this` залишається поточним екземпляром, тобто батьківський метод бачить дані нащадка. ### super і стрілкові функції Стрілкові функції не мають власного `super` і беруть його із зовнішнього контексту, тому в полі-стрілці класу `super` працює: ```javascript class A { hello() { console.log("Hello from A"); } } class B extends A { hello = () => { super.hello(); // works: super is taken from the class body }; } new B().hello(); // "Hello from A" ``` > Пам'ятайте лише, що методи-стрілки створюються на екземплярі, а не в прототипі, тож кожен об'єкт отримує власну копію функції. **Зведення:** | Де використовується | Що робить | | --- | --- | | У конструкторі | Викликає конструктор батька і створює `this` | | У методі | Викликає батьківський метод (`super.method()`) | | У статичному методі | Звертається до статичних методів батька | | Без `extends` | Помилка | | До виклику `super()` | `this` недоступний, буде помилка | ### Типові помилки - Виклик `super()` у класі без `extends`: це `SyntaxError`, бо батька просто немає. ```javascript class A { constructor() { super(); // SyntaxError } } ``` - Присвоєння полів у `this` до `super()`. Порядок завжди такий: спершу `super(...)`, потім `this.x = ...`. - Пропущений `super()` у конструкторі нащадка: конструктор завершиться помилкою, щойно торкнеться `this`. - Очікування, що `super.method()` викличе метод з `this.__proto__`. Ні, `super` прив'язаний до класу, у якому написаний метод, а не до типу поточного об'єкта. - Спроба написати `super.constructor()` замість `super()`. Це різні речі: створює екземпляр саме `super()`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.