Вернуться к уроку

Создать объект тем же конструктором

важность: 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? Вот как это работает:

  1. При вызове new obj.constructor('Петя'), obj ищет у себя свойство constructor – не находит.
  2. Обращается к своему свойству __proto__, которое ведёт к прототипу.
  3. Прототипом будет (*), пустой объект.
  4. Далее здесь также ищется свойство constructor – его нет.
  5. Где ищем дальше? Правильно – у следующего прототипа выше, а им будет Object.prototype.
  6. Свойство Object.prototype.constructor существует, это встроенный конструктор объектов, который, вообще говоря, не предназначен для вызова с аргументом-строкой, поэтому создаст совсем не то, что ожидается, но то же самое, что вызов new Object('Петя'), и у такого объекта не будет name.