Як класи пов'язані з прототипами?
1. Клас: це просто функція
Коли ти оголошуєш клас:
class User {
constructor(name) {
this.name = name;
}
sayHi() {
console.log(`Hi, ${this.name}!`);
}
}JS під капотом перетворює це на щось на кшталт:
function User(name) {
this.name = name;
}
User.prototype.sayHi = function() {
console.log(`Hi, ${this.name}!`);
};Тобто class, це зручна обгортка над функцією-конструктором і її прототипом.
2. Зв'язок між класом і прототипом
Коли ти створюєш екземпляр класу:
const user = new User("Alice");JS робить таке під капотом:
- Створює новий об'єкт:
{} - Встановлює його прототип:
User.prototype - Викликає конструктор:
User.call(this, "Alice")
Тобто:
Object.getPrototypeOf(user) === User.prototype; // true3. Методи класу: це властивості prototype
console.log(Object.getOwnPropertyNames(User.prototype));
// ["constructor", "sayHi"]Кожен метод, який ти пишеш усередині class,
автоматично додається в User.prototype,
а не в сам об'єкт екземпляра.
4. Екземпляри мають спільний прототип
const u1 = new User("Alex");
const u2 = new User("Alice");
console.log(u1.sayHi === u2.sayHi); // true: один метод на всіхЦе і є ключова ідея прототипів:
усі екземпляри розділяють спільні методи через prototype,
щоб не дублювати їх у пам'яті.
5. Успадкування через extends = прототипне успадкування
class Animal {
speak() {
console.log("The animal makes a sound");
}
}
class Dog extends Animal {
bark() {
console.log("Woof-woof!");
}
}
const d = new Dog();
d.speak(); // працюєПід капотом відбувається таке:
// Пов'язує прототипи
Dog.prototype.__proto__ = Animal.prototype;
// Пов'язує конструктори
Object.setPrototypeOf(Dog, Animal);Тобто extends просто створює ланцюжок прототипів:
Dog.prototype → Animal.prototype → Object.prototype6. Ланцюжок прототипів у класах
Для прикладу:
class A {}
class B extends A {}
const b = new B();Ланцюжок буде таким:
b
↓
B.prototype
↓
A.prototype
↓
Object.prototype
↓
nullА для самих конструкторів:
B
↓
A
↓
Function.prototype
↓
Object.prototype
↓
null7. Методи працюють через пошук по ланцюжку прототипів
Коли ти викликаєш b.sayHi(), рушій робить таке:
- Чи є
sayHiв самому об'єктіb? → Ні - Шукає в
B.prototype→ Знайшов, викликає - Якщо ні, йде далі вгору по ланцюжку (
A.prototype,Object.prototype...)
8. Приклад: підтвердження в коді
class Animal {
move() {}
}
class Dog extends Animal {
bark() {}
}
const dog = new Dog();
console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
console.log(Object.getPrototypeOf(Animal.prototype) === Object.prototype); // trueУсе це, це ланцюжок прототипів, створений автоматично при extends.
9. Клас: не магія, просто синтаксичний цукор
Ось еквівалент коду без class:
function Animal() {}
Animal.prototype.move = function() {};
function Dog() {
Animal.call(this);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {};
const dog = new Dog();
dog.bark();Тобто class просто робить цей код красивішим,
автоматизуючи роботу з prototype і Object.create.
Підсумок
| Що | Що клас робить під капотом |
|---|---|
constructor | Функція-конструктор |
| Методи | Записуються в Class.prototype |
extends | Пов'язує прототипи (Child.prototype → Parent.prototype) |
super() | Викликає батьківський конструктор |
instanceof | Перевіряє ланцюжок прототипів |
| Екземпляр | Зберігає дані, а методи бере з прототипу |
Коротко:
Класи в JavaScript, це зручний синтаксис поверх прототипів.
Кожен клас створює:
- функцію-конструктор,
- об'єкт-прототип із методами,
- і ланцюжок успадкування через
__proto__.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.