Создайте новый объект с помощью уже существующего
Представьте, что у нас имеется некий объект 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
, и там тоже нет искомого свойства. - Идя дальше по цепочке, значение
User.prototype
– это пустой объект{}
, чей прототип – встроенныйObject.prototype
. - Наконец, для встроенного
Object.prototype
предусмотрен встроенныйObject.prototype.constructor == Object
. Таким образом, свойствоconstructor
всё-таки найдено.
В итоге срабатывает let user2 = new Object('Pete')
.
Вероятно, это не то, что нам нужно. Мы хотели создать new User
, а не new Object
. Это и есть результат отсутствия конструктора.
(На всякий случай, если вам интересно, вызов new Object(...)
преобразует свой аргумент в объект. Это теоретическая вещь, на практике никто не вызывает new Object
со значением, тем более, в основном мы вообще не используем new Object
для создания объектов).