29 березня 2025 р.

F.prototype

Як відомо, ми можемо створювати нові об’єкти за допомогою функції-конструктора, ось так new F().

Якщо в F.prototype міститься об’єкт, то оператор new автоматично встановлює той об’єкт в [[Prototype]] для новоствореного об’єкта.

Будь ласка, зверніть увагу:

JavaScript використовувала прототипне наслідування з моменту своєї появи. Це одна з особливостей цієї мови.

Але раніше, в давні часи, прямого доступу до прототипа в об’єкта не було. Надійно працювала лише властивість “prototype” функції-конструктора, описане в цьому розділі. Тому ця властивість використовується в багатьох скриптах.

Зауважте, що F.prototype тут є звичайною властивістю, яку назвали "prototype" в об’єкті F. Це звучить дуже співзвучно з терміном “prototype”, але тут це означає всього лиш звичайне ім’я властивості.

Ось приклад:

let animal = {
  eats: true
};

function Rabbit(name) {
  this.name = name;
}

Rabbit.prototype = animal;

let rabbit = new Rabbit("Білий кролик"); //  rabbit.__proto__ == animal

alert( rabbit.eats ); // true

Вираз Rabbit.prototype = animal дослівно означає наступне: “коли буде створено new Rabbit, його властивість [[Prototype]] має посилатись на об’єкт animal”.

Ось кінцева картинка:

На картинці, "prototype" що зображена біля горизонтальної стрілки – це звичайна властивість, а [[Prototype]], що зображена біля вертикальної стрілки – вказує на те, що rabbit успадковує властивості від свого прототипа animal.

F.prototype використовується тільки у в момент виклику функції-конструктора new F

F.prototype використовується тільки при виклику new F і присвоюється в якості властивості [[Prototype]] нового об’єкта.

Якщо після створення властивість F.prototype зміниться (F.prototype = <інший об'єкт>), то нові об’єкти, створені з допомогою new F, будуть мати в якості [[Prototype]] інший об’єкт, а вже існуючі об’єкти будуть посилатись на старий.

Типове значення F.prototype, властивості конструктора

Кожна функція за замовчуванням має властивість "prototype", навіть якщо ми цю властивість самі не прописуємо.

За замовчуванням “prototype” є об’єктом з однією єдиною властивістю constructor, яка посилається на саму ж функцію.

Ось як тут:

function Rabbit() {}

/* значення prototype, яке призначається за замовченням
Rabbit.prototype = { constructor: Rabbit };
*/

Можемо перевірити це:

function Rabbit() {}
// за замовчуванням:
// Rabbit.prototype = { constructor: Rabbit }

alert( Rabbit.prototype.constructor == Rabbit ); // true

Ну й логічно, якщо ми самі нічого з властивістю constructor не робимо, то вона є доступна для всіх об’єктів rabbit через [[Prototype]]:

function Rabbit() {}
// за замовчуванням:
// Rabbit.prototype = { constructor: Rabbit }

let rabbit = new Rabbit(); // успадковує від {constructor: Rabbit}

alert(rabbit.constructor == Rabbit); // true (від прототипу)

Ми можемо використовувати властивість constructor для створення нових об’єктів використовуючи ту саму функцію-конструктор, як і для вже існуючих.

Як тут:

function Rabbit(name) {
  this.name = name;
  alert(name);
}

let rabbit = new Rabbit("Білий кролик");

let rabbit2 = new rabbit.constructor("Чорний кролик");

Це дуже практично у випадку якщо ми маємо об’єкт, не знаємо за допомогою якого саме конструктора той об’єкт був створений (до прикладу якщо він був імпортований з якоїсь бібліотеки), а нам потрібно створити новий об’єкт по типу того, що вже існує.

Але найважливішим моментом щодо "constructor" є те, що…

…Сама мова JavaScript не забезпечує правильного значення "constructor".

Так, constructor існує за замовчуванням у властивостях "prototype" для функцій, але це й усе. Подальша доля "constructor" повністю в наших руках.

А саме, якщо ми замінимо дефолтне значення