Створення нового об’єкта з одинаковим конструктором
Уявіть собі, у нас є довільний об’єкт obj
, який створений функцією-конструктором – ми не знаємо яким саме конструктором, але потрібно створити новий об’єкт використовуючи той самий конструктор.
Чи можна створити новий об’єкт ось так?
let obj2 = new obj.constructor();
Покажіть приклад функції-конструктора для обєкта obj
, який забезпечить правильну роботу такого коду, а також приклад, який, при такому коді, працює неправельно.
Так, ми можемо використовувати такий підхід якщо ми впевнені, що властивість "constructor"
має правильне значення.
Для прикладу, якщо ми не чіпаємо властивість за замовчуванням "prototype"
, тоді цей код буде працювати правильно:
function User(name) {
this.name = name;
}
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // Pete (працює!)
Код працює, тому що User.prototype.constructor == User
.
…Але якщо хтось, якщо можна так виразитись, перезапише User.prototype
і забуде додати властивість constructor
в посиланні властивості об’єкта User
, тоді цей код не буде працювати правильно.
Наприклад:
function User(name) {
this.name = name;
}
User.prototype = {}; // (*)
let user = new User('John');
let user2 = new user.constructor('Pete');
alert( user2.name ); // undefined
Чому user2.name
є undefined
?
Ось тут пояснення як new user.constructor('Pete')
працює:
- Спочатку, здійснюється пошук у властивості
constructor
об’єктаuser
. Нічого не знаходять. - Потім переключаються на ланцюжок прототипу. Прототипом для об’єкта
user
єUser.prototype
, і він також не має властивостіconstructor
(тому що ми “забули” визначити його правильним чином!). - Йдучи далі по ланцюжку прототипу, визначаємо, що
User.prototype
є простий об’єкт, його прототипом є вбудований глобальнийObject.prototype
. - Врешті, для вбудованого
Object.prototype
, є вбудований конструктор глобального об’єктаObject.prototype.constructor == Object
от він і використовується.
Таким чином, в кінці, ми отримуємо let user2 = new Object('Pete')
.
Ймовірно, це не те, що нам потрібно. Ми би хотіли стоврити new User
, а не new Object
. Це і є наслідки пропуску властивості constructor
.
(на випадок, якщо вас зацікавить, виклик new Object(...)
перетворює його аргументи на об’єкт. Це в теорії, але на практиці ніхто не викликає new Object
з аргументами; і загалом, не використовується узагалі new Object
для створення нових об’єктів).