Чим __proto__ відрізняється від prototype?
Коротко
| Властивість | Де знаходиться | Що зберігає |
|---|---|---|
__proto__ | У об'єкта | Посилання на його прототип |
prototype | У функції-конструктора або класу | Об'єкт, який стане прототипом для створюваних об'єктів |
__proto__→ вже створеного об'єктаprototype→ у конструктора (шаблону), за яким створюються об'єкти
Приклад для розуміння
function User(name) {
this.name = name;
}
User.prototype.sayHi = function() {
console.log(`Привіт, ${this.name}`);
};
const tim = new User('Tim');Тепер подивимось, що відбувається:
console.log(tim.__proto__ === User.prototype); // true
console.log(User.prototype.constructor === User); // trueРозшифровка:
User.prototype- це об'єкт, який містить методи (sayHi) і слугує прототипом для всіх об'єктів, створених черезnew User().tim.__proto__- це посилання на той самий об'єктUser.prototype.
Візуально
User (function)
│
├── prototype ──► { sayHi(), constructor: User }
│
└── new User('Tim') → tim {
name: 'Tim',
__proto__: User.prototype
}Тобто __proto__ створеного об'єкта → вказує на prototype функції, яка його створила.
Простими словами
| Властивість | Про що каже | Приклад |
|---|---|---|
prototype | "Що отримають мої діти" | User.prototype.sayHi = ... |
__proto__ | "Хто мій батько" | tim.__proto__ === User.prototype |
Приклад з ланцюжком
function Animal() {}
Animal.prototype.eats = true;
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.barks = true;
const rex = new Dog();
console.log(rex.barks); // true (в Dog.prototype)
console.log(rex.eats); // true (в Animal.prototype)Ланцюжок виглядає так:
rex.__proto__ → Dog.prototype → Animal.prototype → Object.prototype → nullУ всіх об'єктів є __proto__,
а prototype є тільки у функцій і класів
const obj = {};
console.log(obj.__proto__); // Object.prototype
console.log(obj.prototype); // undefined
function Foo() {}
console.log(Foo.prototype); // { constructor: Foo }
console.log(Foo.__proto__); // Function.prototypeУ звичайних об'єктів немає prototype, а у функцій-конструкторів є обидва: і prototype, і __proto__.
У сучасних реаліях
Властивість __proto__ вважається застарілою (legacy). Рекомендується використовувати сучасні аналоги:
Object.getPrototypeOf(obj); // замість obj.__proto__
Object.setPrototypeOf(obj, proto); // замість obj.__proto__ = protoПідсумкова таблиця
| Властивість | Де використовується | Що зберігає | Коли застосовується |
|---|---|---|---|
__proto__ | у об'єкта | посилання на його реальний прототип | коли потрібно дізнатися "хто мій батько" |
prototype | у функції-конструктора або класу | об'єкт, який стане прототипом створюваних об'єктів | коли створюєш методи, доступні всім екземплярам |
Ключовий зв'язок
instance.__proto__ === Constructor.prototypeКожен об'єкт, створений через
new Constructor(), отримує посилання наConstructor.prototypeу своїй внутрішній властивості__proto__.
В одній фразі:
prototype- це "план" або "шаблон", звідки беруться методи для нових об'єктів.__proto__- це "вказівник" об'єкта на той шаблон, звідки він усе успадковує.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.