Чтобы понять объектно-ориентированное программирование в JavaScript, мы сначала должны понять, что JavaScript не является языком на основе классов. Это может немного сбивать с толку, поскольку class - ключевое слово, используемое для синтаксиса. В других языках, таких как ruby, мы определяем классы, которые действуют как «чертежи» для объектов. Они служат шаблонами, а объекты - экземплярами этих классов. Наследование атрибутов и методов происходит через классы.

Однако в JavaScript мы используем только объекты для наследования. Классы были введены в ECMAScript 2015. Он не поддерживает объектно-ориентированное программирование на основе классов. Вы можете думать о классах как о функциях, которые также являются объектами! На самом деле JavaScript - это язык, основанный на прототипах, в котором объекты JavaScripts содержат ссылки или ссылки на другие объекты.

Вот пример.

В этом примере мы объявили объект Pet с помощью метода конструктора. Метод конструктора создает экземпляры объектов со следующими атрибутами: name, species и breed. Затем мы создаем три объекта или трех разных домашних животных, вызывая метод конструктора с new. Чтобы точно узнать, как выглядит первый объект, мы используем console.log(). Затем мы видим в консоли браузера следующее:

Как и ожидалось, мы возвращаем наш объект, который имеет соответствующие атрибуты в качестве свойств. Но внизу мы видим это свойство __proto__. Это ключ к решению того, как наследование работает в JavaScript!

Свойство __proto__ - это частное свойство, содержащее ссылку на другой объект. Этот объект называется его прототипом. Вернемся к примеру и расширим это свойство!

Когда мы раскрываем раскрывающийся список, мы сначала видим метод конструктора, который мы определили в нашем объекте Pet. Это означает, что свойство __proto__ этого объекта связано с прототипом Pet. Вот почему объект может получить доступ к этому методу конструктора. Объект-прототип Pet действует как шаблон и позволяет объекту selene наследовать метод конструктора. А как насчет второго свойства __proto__? Что ж, давайте расширим его!

На этот раз у нас есть больший список! Похоже, свойство Pet __proto__ указывает на другой объект-прототип! Но что это могло быть? Важно помнить, что все объекты в JavaScript на самом деле являются экземплярами Object, класса, представляющего тип данных объекта JavaScript. Глобальный класс Object имеет собственные предопределенные наборы методов и свойств. Эти методы и свойства доступны для объекта Pet. А поскольку объект selene связан с объектом Pet prototype, selene также может получить доступ к этим свойствам. Эта цепочка наследования называется цепочкой прототипов.

Вот визуальное представление того, как выглядит цепочка:

Подведем итоги, потому что это может сбивать с толку! У каждого объекта JavaScript есть объект-прототип. Свойство __proto__ связывает экземпляр объекта с его объектом-прототипом. Этот объект-прототип позволяет наследование методов и свойств. selene наследует методы и свойства от Pet прототипа. Pet prototype имеет свой собственный объект-прототип, который является глобальным Object прототипом. Прототип Pet наследует все методы и свойства, связанные с глобальным прототипом Object.

Как видите, наша цепочка заканчивается глобальным Object прототипом. Это потому, что глобальный прототип Object не имеет собственного объекта-прототипа. Этот метод создания цепочки прототипов будет продолжаться вечно, пока объект не получит значение null для своего объекта-прототипа. Это будет считаться последней цепочкой. Как упоминалось ранее, все объекты JavaScript являются экземплярами Object. Это означает, что глобальный класс Object будет последней цепочкой в ​​этой цепочке наследования!

Различия между классовым и прототипным наследованием

Наследование класса:

  • экземпляры наследуются от классов («чертежи»)
  • создает отношения подкласса

Прототипное наследование:

  • экземпляры наследуются от других экземпляров объекта
  • допускает выборочное наследование

Если вы чем-то похожи на меня, вы можете быть ошеломлены этой новой информацией. Вот список замечательных ресурсов!