Создать объект тем же конструктором
важность: 5
Пусть у нас есть произвольный объект obj
, созданный каким-то конструктором, каким – мы не знаем, но хотели бы создать новый объект с его помощью.
Сможем ли мы сделать так?
var obj2 = new obj.constructor();
Приведите пример конструкторов для obj
, при которых такой код будет работать верно – и неверно.
Да, можем, но только если уверены, что кто-то позаботился о том, чтобы значение constructor
было верным.
В частности, без вмешательства в прототип код точно работает, например:
function User(name) {
this.name = name;
}
var obj = new User('Вася');
var obj2 = new obj.constructor('Петя');
alert( obj2.name ); // Петя (сработало)
Сработало, так как User.prototype.constructor == User
.
Но если кто-то, к примеру, перезапишет User.prototype
и забудет указать constructor
, то такой фокус не пройдёт, например:
function User(name) {
this.name = name;
}
User.prototype = {}; // (*)
var obj = new User('Вася');
var obj2 = new obj.constructor('Петя');
alert( obj2.name ); // undefined
Почему obj2.name равен undefined? Вот как это работает:
- При вызове new
obj.constructor('Петя')
,obj
ищет у себя свойствоconstructor
– не находит. - Обращается к своему свойству
__proto__
, которое ведёт к прототипу. - Прототипом будет (*), пустой объект.
- Далее здесь также ищется свойство constructor – его нет.
- Где ищем дальше? Правильно – у следующего прототипа выше, а им будет
Object.prototype
. - Свойство
Object.prototype.constructor
существует, это встроенный конструктор объектов, который, вообще говоря, не предназначен для вызова с аргументом-строкой, поэтому создаст совсем не то, что ожидается, но то же самое, что вызовnew Object('Петя')
, и у такого объекта не будетname
.