Объектно-ориентированный JavaScript: прототипы
В прошлой статье мы начали рассматривать прототипы и выяснили, что каждый объект может использовать любые методы, которые находятся в функции-конструкторе, с помощью которой данный объект и был создан. Например, обычный массив сам по себе не имеет ни одного метода, но функция конструктор Array
любезно предоставляет ему все методы из своего прототипа в использование.
Разумеется, мы сами можем создавать функции конструкторы и задавать им прототипы. Итак, вы являетесь счастливым владельцем зоопарка. Для каждого животного вы хотите создать объект, содержащий вид и кличку животного. Каждое животное также может издавать звуки. Функция-конструктор в данном случае будет выглядеть следующим образом:
Теперь мы можем создать один или несколько объектов с помощью функции конструктора Animal
и оператора new
:
Каждый созданный нами объект не содержит своего метода speak
. В этом вы можете убедиться, просто выведя объект в консоль console.dir(cat)
. Тем не менее, все созданные объекты могут использовать метод speak
:
Что происходит на самом деле. Когда вы используете метод speak
с объектом, сначала происходит проверка того, есть ли у самого объекта этот метод. Если метода нет, то далее следует проверка на присутствие метода в прототипе. Если метода нет и в прототипе, то метод может быть найден в прототипе прототипа. И так далее, пока выполнение не дойдёт до последнего прототипа, который всегда содержит в себе все методы функции-конструктора Object
. Чтобы в этом убедиться попробуйте выполнить в консоле браузера несколько строчек кода:
Таким образом, созданный нами объект cat
унаследовал все методы не только от функции Animal
, но и от Object
. В этом легко убедиться с помощью использования любого метода объектов, например, toString()
:
Как я уже писал выше, при использовании любого метода сначала проверяется его наличие в самом объекте. Поэтому мы может сами переназначить тот же метод toString
для отдельного объекта cat
:
Или же можно записать данный метод в прототип Animal
, чтобы все создаваемые с помощью этой функции-конструктора объекты использовали именно его:
Теперь объекты dog
и fox
обращаются к прототипу Animal
, а объект cat
имеет собственный метод и использует его.
Есть два способа устанавливать свойства в прототипы для объектов: плохой и хороший. Хороший способ вы уже видели — все примеры приведённые выше написаны с его помощью.
В данном примере к прототипу просто добавляется ещё одно свойство, в независимости от того, что было в прототипе было раньше.
Пример плохого добавления свойств в прототип — непосредственная его перезапись новым объектом:
Почему так делать плохо? Всё просто. Перезаписывая прототип новым объектом, вы полностью стираете все методы, которые были записаны в него ранее. Поэтому в приведённом выше примере метода toString
у всех объектов, созданных с помощью функции-конструктора Animal
, не будет.
Комментарии