Skip to main content
Практика завдань

Прототипи та прототипне наслідування в JavaScript

Прототипне наслідування є основою об'єктної моделі в JavaScript. На відміну від класичних мов (Java, C++), які використовують класичне наслідування, JavaScript реалізує динамічну модель, де об'єкти можуть успадковувати пропси та методи один від одного через прототипи.


Що таке Прототип?

Прототип — це об'єкт, на який будь-який інший об'єкт посилається, якщо він не має шуканої пропси чи методу. Кожен об'єкт у JavaScript може мати інший об'єкт, призначений як його прототип. Якщо властивість не існує на самому об'єкті під час доступу, інтерпретатор "підніметься" по ланцюгу прототипів до тих пір, поки не знайде потрібну властивість або не досягне об'єкта null.

childObject

parentObject

Object.prototype

null

  • childObject: об'єкт, в якому виконується пошук пропси.
  • parentObject: прототип childObject.
  • Object.prototype: базовий прототип, від якого успадковують всі об'єкти, якщо не вказано інше.
  • null: кінець ланцюга; якщо властивість не знайдена до цього моменту, результат буде undefined.

Властивість [[Prototype]] та proto

У специфікації ECMAScript кожен об'єкт має внутрішню властивість [[Prototype]], що вказує на прототип. Історично багато середовищ (наприклад, браузери) надають геттер/сеттер __proto__ для доступу до неї, але це вважається застарілим.

Сучасний спосібObject.getPrototypeOf та Object.setPrototypeOf

javascript
const parent = { greet: function() { console.log("Hello!"); } }; const child = {}; // Встановлюємо parent як прототип child Object.setPrototypeOf(child, parent); // Тепер child має доступ до greet() через ланцюг прототипів child.greet(); // "Hello!" console.log(Object.getPrototypeOf(child) === parent); // true

Object.create

Найзручніший спосіб створити об'єкт з потрібним прототипом — це використання методу Object.create

javascript
const person = { sayName() { console.log(`My name is ${this.name}`); }, }; const john = Object.create(person); john.name = "John"; john.sayName(); // My name is John
  • person виступає як "батько" (прототип).
  • john — новий об'єкт, чий [[Prototype]] вказує на person.

Ланцюг Прототипів

Якщо ми викликаємо властивість/метод john.sayName(), і john не має такої пропси, JS шукатиме цю властивість у person. Якщо person не має sayName, інтерпретатор перейде до person.__proto__, який зазвичай є Object.prototype, і так далі.

Конструкторські Функції та Властивість прототипу

Перед появою класів в ES6 (ES2015) конструкторські функції часто використовувалися для імітації поведінки класу.

javascript
function User(name) { this.name = name; } User.prototype.sayHi = function () { console.log(`Hi, I'm ${this.name}`); }; const alice = new User("Alice"); const bob = new User("Bob"); alice.sayHi(); // "Hi, I'm Alice" bob.sayHi(); // "Hi, I'm Bob"
  • User — це конструкторська функція.
  • Властивість User.prototype автоматично створюється, коли функцію оголошено, і вона стає прототипом для всіх об'єктів, створених за допомогою new User(...).
  • alice та bob зберігають посилання на властивість екземпляра name, а методи беруться з User.prototype.

Класи та Прототипне Наслідування

У сучасних версіях JS ви можете використовувати клас, який під капотом все ще працює на прототипах:

javascript
class Person { constructor(name) { this.name = name; } greet() { console.log(`Hello, I'm ${this.name}`); } } const tom = new Person("Tom"); tom.greet(); // "Hello, I'm Tom" // Перевірка прототипу console.log(Object.getPrototypeOf(tom) === Person.prototype); // true
  • Компілер створює конструкторську функцію Person і встановлює властивість Person.prototype. Усі методи, визначені всередині class Person {}, записуються в Person.prototype.

Підсумок

  • Прототип — це механізм, що дозволяє об'єктам успадковувати пропси та методи від інших об'єктів.
  • У JS кожен об'єкт має приховану властивість [[Prototype]], зазвичай посилаючись на інший об'єкт або null.
  • Ланцюг прототипів дозволяє шукати властивість "знизу-вгору": від об'єкта до його прототипу, потім до прототипу прототипу і так далі.
  • Конструкторські функції (до ES6) та класи (з ES6) використовують прототипи "під капотом". Класи є просто "синтаксичним цукром" над конструкторськими функціями.
  • Object.create — зручний спосіб створення об'єктів, вказуючи прототип безпосередньо. Прототипне наслідування забезпечує потужний, гнучкий підхід до реалізації ООП без суворого зв'язування з класами.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань