Вы, наверное, знаете, как работает ООП. Класс Dog наследуется от класса Animal, что означает, что если у вас есть Dog, вы получаете доступ к методам из Animal. На самом деле это всего лишь подмножество ООП. Вы можете быть объектно-ориентированным без классов, и это то, что делает JavaScript.

Класс - это план. Он содержит информацию о том, что есть у каждого экземпляра этого класса . Он сообщает вам, какие методы и свойства существуют и как вы можете использовать этот класс вещей.

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

Разница между экземплярами и классами фундаментальна для понимания ООП большинством людей. Но это не обязательно для ООП. Есть способ использовать ООП без классов. В конце концов, это объектно-ориентированное программирование: в центре внимания шоу - объекты, а не классы.

Стиль ООП, в котором нет разницы между классами и объектами, называется программированием на основе прототипов (чтобы облегчить нашу жизнь, мы будем называть его PBP).

В PBP каждый объект может быть индивидуальным. Он содержит оба своих метода и одновременно данные. Обычно вы можете добавлять новые свойства и методы к объекту, когда захотите, даже во время работы программы.

Если это звучит так, как будто только несколько программистов используют для решения своих краевых задач, вы будете удивлены. Одним из самых популярных языков в мире является язык PBP: JavaScript.

В JavaScript нет классов в ООП-смысле слова, основанном на классах. JavaScript работает с объектами. Если вы хотите инкапсулировать вместе несколько функций и свойств, вы должны создать объект, содержащий функции и свойства, а не класс.

const animal = {
    numberOfLegs: 4,
    sleep: () => print("Zzz")
}

Это объект, у которого есть свойство и функция, которая выполняет некоторую работу. Это отличается от класса, потому что функция сама является частью данных, которые есть у объекта. Оно так же изменчиво, как состояние свойства.

animal.sleep = null

Теперь, внезапно, у животного больше нет функции. У JavaScript нет чертежей, у него есть только дома.

А как насчет наследования?

Основным свойством класса является то, что он может наследовать методы и свойства от других классов. И House, и Apartment могут наследовать от Residence, чтобы не дублировать один и тот же код в обоих классах.

Но опять же, классы не нужны для наследования. В PBP наследование полностью осуществляется с помощью объектов.

Ранее я упоминал, что в PBP объект содержит все свои методы и свойства, а также их фактическое состояние. Таким образом, единственный способ унаследовать все это - скопировать (или сделать ссылку) на все эти методы и свойства. Именно это и делают языки PBP, и это называется прототипное наследование.

Если мы хотим создать объект dog, который будет иметь доступ к тем же методам, что и animal, мы можем просто сделать dog содержать animal, поскольку методы находятся внутри animal.

const dog = {
    prototype: animal,
    bark: () => print("Woof!")
}

Если мы хотим заставить dog есть пищу, мы можем сделать следующее:

dog.prototype.eatFood(10)

К счастью, JavaScript автоматически вызывает функции прототипа. Если функция не существует для этого объекта, он будет искать функцию в прототипе. Прототип может сам содержать другой прототип, поэтому JS будет выполнять поиск до тех пор, пока не найдет искомую функцию.

Причина, по которой они называются языками на основе прототипов, заключается в том, что прототип, в отличие от класса, является конкретным. Прототип - это рабочая вещь, а не чертеж. Возможно, вы не захотите продавать прототип миллионам клиентов, но это действительно работает. Затем вы используете этот прототип для создания кучи копий, которые вы действительно будете использовать. Прямо как на фабрике.

Объект animal - прототип животного. Это такой же объект, как и любой другой, но он будет использоваться для создания новых, конкретных животных, таких как dog.

Это лучше, чем классы?

PBP более прост, чем ООП на основе классов. Он имеет меньше движущихся частей и полностью прозрачен. Вы можете увидеть, как это работает. ООП на основе классов - это дополнительный слой абстракции. Это означает, что у PBP есть много преимуществ, но есть и недостатки.

Главное преимущество PBP заключается в его гибкости. Чертежи - это то, что нужно делать заранее, и они должны быть правильными. Если вы строите дом, у вас будет много проблем, если вы поймете, что на полпути к постройке крыши вы забыли добавить окно в чертеж. Классы похожи: вы создаете их до создания и использования объектов. Вы должны знать, какие методы и свойства вам понадобятся, прежде чем начать его использовать. Независимо от того, насколько вы хороши в программировании, вы не сможете все предсказать.

Если вам не нужно создавать класс заранее, вы можете сразу приступить к созданию своих объектов. Вы можете адаптировать их по мере использования без больших затрат. Это очень полезно в программировании, где требования все время меняются. Вам нужна возможность быстро и легко меняться.

Но быстрое и легкое изменение сопряжено с большим риском: правильностью. Существуют чертежи, позволяющие спланировать дом еще до его постройки, поэтому ошибки обнаруживаются на ранней стадии, и рабочие не теряются во время строительства. Если вы попытаетесь построить дом, просто сделав это и посмотрев, куда он вас приведет, вы, вероятно, закончите тем, что дом рухнет на вас. То же самое и с программированием: вам нужно убедиться, что ваша кодовая база правильная и правильная. Если каждый сможет просто пойти и начать все менять, она быстро рухнет на себя.

Как и все в программировании, PBP и ООП на основе классов попадают в спектр компромиссов. С одной стороны, PBP гибок, с ним легко работать, что ускоряет разработку. С другой стороны, ООП на основе классов является более жестким и надежным, что приводит к меньшему количеству ошибок. Для решения различных задач требуются разные инструменты, и, зная PBP, вы лучше подготовлены для решения проблем, для которых это необходимо. Удачного кодирования!

Примечание. Это репост с сайта programmingwords.com. Это блог, в котором каждый месяц публикуются два новых термина из области компьютерных наук. Проверьте это, если вас интересуют compsci, компиляторы или языки программирования! :)

Использованная литература:

Программирование на основе прототипов
https://en.wikipedia.org/wiki/Prototype-based_programming

Наследование и цепочка прототипов - JavaScript
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain