Сегодня мы поговорим с вами о том, как автоматически привязывать прототип для всех вновь создаваемых объектов при помощи конструктора. Допустим, у нас есть конструктор студентов, который на вход принимает имя этого студента и записывает его в поле name. Помимо каких-то характеристик для студента, нам хотелось бы добавить в него несколько методов и логично было бы хранить их в прототипе. Для того чтобы автоматически привязывать этот прототип для всех вновь создаваемых студентов, нам необходимо поместить его в специальное хранилище. Данное хранилище есть у каждой функции конструктора. И оно расположено в специальном поле prototype. Конструктор в момент исполнения выполняет дополнительный шаг, который привязывает тот объект, который мы поместили в хранилище, в качестве прототипа для всех вновь создаваемых объектов, в нашем случае – для всех студентов. И создавая новых студентов при помощи нашего конструктора, мы увидим, что у каждого из них внутреннее поле prototype будет ссылаться на тот объект, который мы ранее поместили в хранилище. Данное хранилище может вам напомнить другое хранилище, а именно то, которое расположено в специальном поле prototype функции Object. Напомню, что это хранилище хранит общие методы, полезные для всех объектов. И более того, автоматически каждый создаваемый объект в JavaScript имеет в качестве прототипа объект этого хранилища. Изначально нам было не очень очевидно, каким же образом осуществлялась данная привязка, ведь мы создавали объекты при помощи литеральной конструкции, а не конструктора и оператора new. Но на самом деле под капотом интерпретатор вызывает тот же самый конструктор Object оператором new, и все становится на свои места. Давайте подробнее поговорим про специальное поле .prototype. Мы выяснили, что оно есть у каждой функции, даже такой бесполезной как эта. Оно хранит некоторый объект и этот объект имеет смысл только, когда мы вызываем функцию как конструктор. Изначально этот объект не пустой и хранит специальное поле – .constructor. Давайте поговорим о нем подробнее. Оно неперечисляемое и хранит ссылку на саму эту функцию. Таким образом, обращаясь к этому полю, мы можем получить доступ к конструктору. Для чего это может быть полезно? Например, мы можем выяснить имя конструктора конкретного объекта. Например, если мы сконструировали нового студента Billy на основе конструктора Student, мы можем обратиться к этому полю у Billy. У Billy этого поля, естественно, нет, но оно есть в прототипе, который, как мы знаем, изначально хранится в хранилище Student.prototype. И так как данное поле хранит ссылку на функцию, мы можем посмотреть имя этой функции, обратившись к полю name. Таким образом, мы выясним, что Billy в качестве конструктора, имеет функцию с названием Student. Важно помнить о поле .constructor, так как мы очень легко можем его перезаписать. В нашем случае мы это и сделали. Мы просто поместили в поле .prototype, в это хранилище, новый объект, тем самым уничтожив поле .constructor. Чтобы этого не произошло, достаточно не перезаписывать тот объект, который хранится изначально в этом хранилище, а дополнять его новыми методами. Таким образом, мы получим на основе этого конструктора новые объекты, которые будут иметь доступ как к методам из прототипа, так и к специальному полю .constructor.