Ланцюжок прототипів
ланцюжок прототипів (prototype chain) - це механізм успадкування в JavaScript, через який під час звернення до властивості чи методу об'єкт шукає його не лише в себе, але й у своїх "батьків" (прототипів).
Коротко
Кожен об'єкт у JS має приховане посилання на інший об'єкт -
свій прототип ([[Prototype]]),
і якщо потрібна властивість не знайдена в самому об'єкті,
JS шукає її в прототипі, потім у прототипі прототипу і так далі,
поки не дійде до null.
Ця послідовність і називається ланцюжок прототипів.
Приклад - базовий
const animal = { eats: true };
const dog = Object.create(animal); // dog успадковує від animal
dog.barks = true;
console.log(dog.barks); // true (знайшов у dog)
console.log(dog.eats); // true (знайшов у animal)
console.log(dog.toString); // [Function: toString] (успадковано від Object.prototype)Що відбувається:
dog -> animal -> Object.prototype -> nullJS йде по ланцюжку:
- Шукає
barksуdog-> знайдено - Шукає
eatsуdog-> немає -> йде вanimal-> знайдено - Шукає
toString-> немає вanimal-> йде вObject.prototype-> знайдено - Далі
Object.prototype.__proto__=null-> кінець ланцюжка
Візуально
dog {
barks: true
}
^
animal {
eats: true
}
^
Object.prototype {
toString(), hasOwnProperty(), ...
}
^
nullПриклад з методами
const animal = {
walk() {
console.log('Тварина йде');
}
};
const dog = Object.create(animal);
dog.bark = function() {
console.log('Гав!');
};
dog.walk(); // "Тварина йде" (метод знайдено у прототипу)
dog.bark(); // "Гав!" (метод знайдено у dog)JS не копіює методи, а знаходить їх під час виклику через ланцюжок.
Перевірка прототипу
console.log(Object.getPrototypeOf(dog) === animal); // trueМожна також перевірити за допомогою оператора instanceof:
console.log(dog instanceof Object); // true (тому що в ланцюжку є Object.prototype)Приклад з класами (той самий принцип)
class Animal {
eat() { console.log('Їм'); }
}
class Dog extends Animal {
bark() { console.log('Гав'); }
}
const rex = new Dog();
rex.bark(); // "Гав"
rex.eat(); // "Їм" (успадковано від Animal)Під капотом це той самий механізм:
rex -> Dog.prototype -> Animal.prototype -> Object.prototype -> nullЯкщо властивість знайдено - пошук зупиняється
const animal = { eats: true };
const dog = Object.create(animal);
dog.eats = false;
console.log(dog.eats); // false (знайшов у самому dog, далі не шукає)JS завжди використовує першу знайдену властивість у ланцюжку.
Можна змінити прототип вручну (але небажано)
const cat = { meow: true };
Object.setPrototypeOf(dog, cat);
console.log(dog.meow); // trueТак можна перебудувати ланцюжок, але це повільно і зазвичай не рекомендується робити в продакшені.
Підсумок
| Етап | Що відбувається |
|---|---|
| 1 | JS шукає властивість у самому об'єкті |
| 2 | Якщо немає - йде у прототип ([[Prototype]]) |
| 3 | Потім - у прототип прототипу |
| 4 | І так далі, поки не дійде до null |
| Якщо не знайдено ніде | Повертає undefined |
Приклад підсумкової схеми
rex -> Dog.prototype -> Animal.prototype -> Object.prototype -> null| Рівень | Де зберігається | Приклад |
|---|---|---|
| rex | власні властивості | rex.name = 'Rex' |
| Dog.prototype | методи класу Dog | bark() |
| Animal.prototype | методи базового класу | eat() |
| Object.prototype | стандартні методи | toString(), hasOwnProperty() |
В одній фразі:
Ланцюжок прототипів - це шлях, яким JavaScript шукає властивості й методи, переходячи від об'єкта до його прототипу, поки не знайде потрібне або не дійде до
null.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.