Первый шаг - понять, что такое constructor
и prototype
. Это не сложно, но нужно отказаться от «наследования» в классическом смысле.
Конструктор
Свойство constructor
не вызывает каких-либо особых эффектов в вашей программе, кроме того, что вы можете посмотреть на него, чтобы узнать, какая функция использовалась вместе с оператором new
для создания вашего объекта. Если вы ввели new Bar()
, это будет Bar
, а вы ввели new Foo
, это будет Foo
.
Прототип
Свойство prototype
используется для поиска в случае, если у рассматриваемого объекта нет запрошенного свойства. Если вы напишите x.attr
, JavaScript попытается найти attr
среди атрибутов x
. Если он не может найти его, он будет выглядеть в x.__proto__
. Если его там тоже нет, он будет выглядеть как x.__proto__.__proto__
и так далее, пока определено __proto__
.
Так что же такое __proto__
и какое оно имеет отношение к prototype
? Вкратце, prototype
для «типов», а __proto__
для «экземпляров». (Я говорю это с кавычками, потому что нет никакой разницы между типами и экземплярами). Когда вы пишете x = new MyType()
, что происходит (среди прочего), что x.__proto___
устанавливается на MyType.prototype
.
Вопрос
Теперь вышесказанное должно быть всем, что вам нужно, чтобы понять, что означает ваш собственный пример, но попытаться ответить на ваш реальный вопрос; "зачем писать что-то вроде":
Bar.prototype.constructor = Bar;
Лично я никогда не видел его, и я нахожу это немного глупым, но в указанном вами контексте это будет означать, что Bar.prototype
-объект (созданный с помощью new Foo(42)
) будет выглядеть как созданный Bar
, а не Foo
. Я предполагаю, что идея состоит в том, чтобы сделать нечто похожее на языки, подобные C ++ / Java / C #, где поиск по типу (свойство constructor
) всегда будет приводить к наиболее конкретному типу, а не к типу более общего объекта, который находится выше в прототип цепи.
Мой совет: не думайте особо о «наследовании» в JavaScript. Концепции интерфейсов и микшинов имеют больше смысла. И не проверяйте объекты на предмет их типов. Вместо этого проверьте требуемые свойства («если он ходит как утка и крякает как утка, значит, это утка»).
Попытка ввести JavaScript в классическую модель наследования, когда все, что у него есть, это механизм-прототип, как описано выше, и вызывает путаницу. Многие люди, которые предлагали установить свойство constructor
вручную, вероятно, пытались сделать именно это. Абстракции хороши, но это ручное присвоение свойства конструктора не очень идиоматическое использование JavaScript.