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

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

В Javascript наследование реализуется через его прототип, отсюда и концепция прототипно-ориентированного программирования. У объектов есть особое свойство, этот объект называется «прототип». Это либо null, либо ссылка на другой объект.

Чтобы объяснить эту концепцию, мы собираемся смоделировать простую систему опроса.

Давайте начнем

В простой системе голосования должен быть человек, организующий мероприятие, и несколько избирателей. Внедрение всего этого в приложение потребует от организатора (администратора) и избирателя создания учетной записи. Администратор сможет создать мероприятие и добавить в него участников, а избиратель сможет проголосовать. Они уникальны для каждого пользователя, но похоже, что и администратор, и избиратель могут создать учетную запись, а также просматривать результаты опросов.

Во-первых, мы собираемся создать фиктивную базу данных для временного хранения наших данных.

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

Отлично, мы создали наш конструктор. Теперь давайте посмотрим, что происходит, когда мы пытаемся создать учетную запись.

Теперь давайте создадим еще один конструктор для наших избирателей.

То же самое, что произошло в админке, происходит и с избирателями, когда мы создаем учетную запись методом .createAccount. Единственная проблема здесь заключается в том, что и пользователь, и администратор технически делают одно и то же (отправляются в одну и ту же базу данных, но в разные массивы и выводят одну и ту же структуру результата), и мы все еще повторяем код.

Прототипы JavaScript

Что, если бы существовал способ иметь метод .createAccount в одном конструкторе, от которого и администратор, и избиратель могли бы наследовать. По этой причине объект-прототип был реализован в Javascript. Например, наш конструктор Admin поставляется с объектом-прототипом. Давайте попробуем получить доступ к прототипу администратора в консоли нашего браузера.

Если вы заметили, как и любое другое свойство Object в javascript, мы обращались к нашему прототипу с помощью записи через точку .. По умолчанию прототип конструктора имеет свойство конструктора, для которого задан сам конструктор. Другими словами

Admin.prototype.constructor = Admin

Рефакторинг кода

Давайте рефакторим наш код, чтобы реализовать концепцию прототипа.

Поскольку и Admin, и Voter являются пользователями в нашем приложении, мы можем создать новый конструктор с именем User, который имеет те же свойства, что и Admin и Voter.

Подождите минутку, мы собираемся добавить наш метод createAccount, но на этот раз в прототипе пользователя.

Вот и наш первый шаг к наследованию. Мы уже обслуживали как администратора, так и избирателя только в одной функции (мы скоро установим роль в условии). Теперь давайте сделаем так, чтобы Admin и Voter наследовали метод .createAccount из конструктора User.

В приведенном выше фрагменте мы использовали метод Object.create для создания копии прототипа User в прототипе Admin (обратите внимание, что эта копия будет иметь ту же ссылку в памяти, поэтому, если мы рефакторим метод в User, он также изменится в Admin). ). Теперь, когда администратор унаследовал от пользователя, давайте посмотрим, что находится в прототипе администратора с помощью консоли браузера.

Поскольку администратор наследуется от пользователя, для конструктора администратора задано значение пользователя. Поскольку мы хотим наследовать только прототип Admin, а не сам конструктор, давайте это исправим.

Теперь снова проверьте с помощью консоли.

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

Давайте сделаем так, чтобы Voter наследовал от пользователя к. Точно так же, как админ

Мы создали один и тот же метод .createAccount как для администратора, так и для пользователя, но на этот раз не дублировали коды и не писали меньше кодов.

Теперь давайте добавим еще несколько функций в наше приложение для опросов.

Поиск событий и просмотр результатов

И администратор, и избиратель должны иметь возможность искать событие и просматривать результаты опросов, поэтому мы поместим этот метод в прототип конструкции пользователя, чтобы оба могли его наследовать.

Создать и удалить мероприятие

Поскольку администратор будет создавать событие, администратор должен быть единственным, кому разрешено удалять. Поэтому мы поместим это в прототип администратора, а не в прототип пользователя, чтобы избиратель не унаследовал этот метод.

Проголосовать за участника

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

Сложность создания учетной записи (.createAccount) скрыта от избирателя и администратора, поэтому используется абстракция.

.searchEvent , .viewresults и некоторые другие методы могут принимать любую форму в зависимости от того, где они используются, либо в Admin, Voter, либо в самом конструкторе User, тем самым отображая полиморфизм. Например, предположим, что мы хотим, чтобы метод .viewResults в избирателе давал ответ, отличный от ответа администратора, мы можем сделать это

Это объясняет Полиморфизм (один и тот же метод, .viewResults, дает другой ответ).

Да да! Мы сделали. Теперь давайте создадим файл index.js, чтобы мы вызывали все наши методы.

Другие функции, которые здесь не реализованы: автоинкрементный идентификатор пользователя, проверка с помощью шутки. Можно найти в моем репозитории GitHub