Первый шаг — понять, что такое 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.
person
Jakob
schedule
25.10.2010