Классы JavaScript будут обсуждаться в этой статье. Объекты JavaScript уже были замечены, а классы — это чертежи или шаблоны для создания объектов.

Здесь обсуждается ряд вещей, которые не будут звучать слишком незнакомыми или революционными.

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

Для компьютерных наук в целом важно объектно-ориентированное программирование и классы. Однако когда дело доходит до JavaScript, это не всегда так. В классах JavaScript есть нечто особенное по сравнению с другими языками программирования. Функции класса скрыты под поверхностью классов. Функции-конструкторы на самом деле представляют собой еще один способ определения объектов. Цель этой статьи — объяснить, что такое классы и как мы можем их использовать и создавать. По ходу будут затронуты следующие темы:

  • Объектно-ориентированного программирования
  • Классы и объекты
  • Классы
  • Наследование
  • Прототипы

Объектно-ориентированное программирование

Было бы неплохо кратко упомянуть об объектно-ориентированном программировании (ООП), прежде чем мы перейдем непосредственно к занятиям. Объектно-ориентированное программирование — это парадигма структурирования кода как объектов, что упрощает его поддержку и повторное использование. Использование ООП учит вас думать обо всех видах тем в объектах, объединяя свойства в схемы, называемые классами, чтобы обернуть их в схему. Родительский класс может наследовать свойства этого класса.

Домашнее животное может иметь определенные свойства, такие как имя, вес, рост, максимальная скорость, цвет и т. д. Мы можем повторно использовать все свойства слова «животное» и добавить несколько свойств, специфичных для рыб, если мы думаем о конкретном виде рыб. . Собаки такие же; если мы рассмотрим собаку, все свойства «животного» могут быть повторно использованы и добавлено несколько свойств, характерных для собак. Таким образом можно повторно использовать наш класс животных.

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

В этом отношении очень важны объектно-ориентированные языки программирования, такие как Java и .NET. Объекты не обязательно находятся в центре внимания JavaScript. Однако они не являются звездой нашего кода. Мы будем использовать их, и они нам понадобятся.

Классы и объекты

Основная концепция объекта состоит в том, что он состоит из свойств и методов. Важно давать осмысленные имена свойствам объекта. Например, объект с именем person может иметь свойства age и lastName, которые содержат значения. Ниже приведен пример объекта:

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

В этом коде определяется класс с именем ClassName, объявляется объектная переменная и объект инициализируется новым экземпляром. Аргумент предоставляется, а также аргумент. Инициализация свойства будет выполняться конструктором с использованием этих аргументов. Параметры конструктора (prop1 и prop2) и свойства (prop1) класса имеют одинаковые имена. Всякий раз, когда ключевое слово this появляется перед свойством класса, вы можете его распознать. Экземпляры ClassName содержат это как первое свойство, потому что оно соответствует объекту, на который ссылается ключевое слово.

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

В качестве альтернативы использованию синтаксиса класса пример с собакой можно было бы сделать с использованием синтаксиса класса. Результат был бы следующим:

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

Будет выведено следующее:

JavaScript is a chihuahua and weighs 2.4 kg.

Части класса будут обсуждаться в следующем разделе.

Классы

Вам может прийти в голову вопрос, зачем вообще нужны классы, если классы не делают ничего, кроме определения объектов? Класс — это, по сути, схема для создания объекта. С классом собак создать 20 собак намного проще, когда нам нужно печатать гораздо меньше. Имена всех свойств должны указываться каждый раз при создании объектов. Также существует вероятность опечатки и неправильного написания имени свойства. Эти типы ситуаций требуют использования классов.

В предыдущем разделе мы объяснили, как создать класс, используя ключевое слово class в JavaScript. Следующим шагом является присвоение имени классу. Заглавная буква является соглашением при именовании классов.

Давайте рассмотрим различные элементы класса.

Конструкторы

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

Здесь показан конструктор класса Person:

Этот конструктор является основой специальной функции, которую создает JavaScript. Будет создан новый объект с заданными свойствами с использованием имени класса. С помощью этой специальной функции можно создать экземпляр класса (объект).

Новый объект Person можно создать следующим образом:

JavaScript ищет специальную функцию-конструктор в классе Person и создает объект, используя новое слово. Экземпляр человека с указанными свойствами возвращается конструктором. В переменной p хранится этот объект.

Мы можем видеть, что свойства действительно установлены, если мы используем нашу новую переменную p в операторе регистрации:

В результате получается:

Привет Маайке

Можете ли вы сказать мне, что, по вашему мнению, произойдет, если мы не добавим все свойства в класс? Давайте взглянем:

Однако JavaScript не рухнет. Устанавливаются только неопределенные свойства. Можно увидеть, что происходит, зарегистрировав это:

В результате получаем:

Привет Маайке undefined

Значения по умолчанию могут быть указаны в конструкторах. Процедура будет следующей:

В этом случае Hi Maaike было бы напечатано как Hi Maaike Doe вместо Hi Maaike undefined.

Методы

Функции могут быть указаны в классе. Используя собственные свойства объекта, наш объект может выполнять действия, например печатать свое имя. У классов есть методы, которые являются их функциями. Ключевое слово function не используется при определении этих методов. Для начала назовем его:

Объекты Person можно приветствовать, вызвав метод приветствия следующим образом:

Вывод будет следующим:

Всем привет! Я Маайке

Количество методов, которые вы можете указать в классе, не ограничено. В этом примере используется свойство firstname. Используя this.property, мы делаем это. Следующее было бы напечатано, если бы для свойства firstname было установлено другое значение, например, Rob:

Всем привет! я Роб

Параметры также могут передаваться методам, и они также могут возвращать результаты:

Комплемент не имеет собственного вывода, поэтому мы его регистрируем.

Вывод будет следующим:

Это замечательная шляпа, Гарри

Как заметил Маайке, вы обычно не дополняете свои собственные свойства, поэтому мы отправляем параметры в наш метод. Тем не менее, когда методу требуются только свойства объекта и не требуется внешний ввод, параметры не требуются, и метод может просто использовать свойства объекта. Вот упражнение, которое подготовит вас к использованию свойств вне вашего класса.

Характеристики

Часто называемые полями, свойства содержат данные класса. Когда мы создавали их в наших конструкторах, мы видели один тип свойства:

Имя и фамилия — это два свойства, которые Person получает от своего конструктора. Добавление или удаление свойств аналогично добавлению или удалению объектов. Когда мы получили доступ к этим свойствам из экземпляра вне класса, мы увидели, что они доступны извне класса:

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

Таким образом можно добавить свойство, к которому нельзя получить доступ извне. Символ # используется для префикса:

На данный момент невозможно получить доступ к свойствам firstname и lastname вне класса. Этого можно добиться, добавив # перед свойством. В качестве примера:

Будет предоставлено следующее:

неопределенный

В нашем конструкторе мы могли бы изменить его так, чтобы мы могли создавать только объекты, имена которых начинаются с «М»:

Теперь вам нужно будет добавить букву М перед значением имени, если оно не начинается с «М». Имя, такое как Мкей, будет выглядеть так:

В этом примере проверки нет ничего глупого. Конструктор не позволяет нам получить к нему доступ извне класса. Он доступен только внутри класса. Здесь в игру вступают геттер и сеттер.

Геттеры и сеттеры

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

Получение и установка — первые ключевые слова в этих средствах доступа. По возможности поля должны быть закрытыми и доступными только через геттеры и сеттеры. В результате объект не может управляться извне, не зная его свойств. Инкапсуляция — это принцип инкапсуляции. Данные инкапсулируются в классы, а объекты управляют своими собственными полями.

Вы можете сделать это, выполнив следующие действия:

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

Вывод будет следующим:

Мария

Был создан новый объект Person с именем Maria и фамилией Saga. Используя метод доступа геттера, мы можем отобразить первое имя в выводе. Также есть сеттер для изменения значения. Чтобы изменить имя с Марии на Аднан, выполните следующие действия.

В настоящее время сеттер ничего особенного не делает. Как и в конструкторе ранее, мы могли бы выполнить проверку следующим образом:

Имя будет проверено, чтобы увидеть, начинается ли оно с буквы М, и если да, оно будет обновлено до любого параметра имени. Параметр будет объединен с M, если это не так.

Имя не используется как функция. Две круглые скобки () означают, что это не функция, поэтому вы фактически получите ошибку.

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

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

Примером очень простого класса Vehicle может быть:

Наш класс Vehicle имеет два метода: move и Acceleration. С помощью ключевого слова extends можно было бы создать класс Motorcyle, наследуемый от этого класса:

Мы указываем, что определенный класс принадлежит другому классу с помощью ключевого слова extends. В этом примере мотоцикл относится к классу транспортных средств. Наш класс Motorcycle сможет получить доступ к свойствам и методам из Vehicle. DoWheelie() — это новый метод, который мы добавили. Действие специфично для определенных транспортных средств, поэтому добавлять его в класс Vehicle не имеет смысла.

Как вы можете видеть в конструкторе, слово super вызывает конструктор из родителя, которым в данном случае является конструктор Vehicle. Таким образом, все поля и методы наследуются от родителя автоматически, без необходимости делать что-либо еще. Всякий раз, когда вы находитесь в классе, который наследуется от другого класса, вы должны вызывать super(), иначе вы получите ReferenceError.

Наш доступ к Транспортным средствам в мотоциклах позволяет нам делать это:

Вывод будет следующим:

Black
moving at 50

Наш класс Vehicle не имеет свойств или методов, специфичных для мотоциклов. Учитывая, что не каждое транспортное средство является мотоциклом, мы не уверены, что получим свойства или методы от ребенка.

Здесь пока нет геттеров и сеттеров, но мы, безусловно, могли бы их использовать. Точно так же, если у родительского класса есть геттеры и сеттеры, дочерний класс наследует их. Сделав это, мы могли контролировать, какие свойства извлекались и изменялись (и как). Как правило, в этом нет ничего плохого.

Прототипы

В JavaScript прототипы позволяют создавать объекты. Объекты наследуются от прототипа Object.prototype при отсутствии спецификации класса. Использование этого класса JavaScript довольно сложно. Пока мы рассматриваем его как базовый объект, который всегда находится на вершине нашего дерева наследования, нам не нужно беспокоиться о том, как он реализован в JavaScript.

Во всех классах есть свойство прототипа с именем «прототип», доступ к которому можно получить следующим образом:

ClassName.prototype

Свойство прототипа можно использовать для добавления функции в класс. Для этого будет использоваться наш класс Person:

Добавление функции в прототип происходит следующим образом:

Прототип — это свойство, которое содержит все свойства и методы объекта. Функция-прототип аналогична функции класса. С помощью функции Introduction в нашем коде мы добавили свойства и методы к объекту, используя прототип. Для свойств вы можете сделать то же самое:

Затем экземпляры Person могут вызывать их:

Будет выведено следующее:

зеленый

Привет, я Мария

Класс будет создан со значением по умолчанию и любимым цветом. Все экземпляры и будущие экземпляры будут иметь к ним доступ.

Методы и свойства, определенные через прототип, обрабатываются так, как если бы они были определены в классе. В результате перезапись одного экземпляра не влияет на все экземпляры. Значение FavoriteColor нашего объекта Person с именем Мария не изменилось бы, если бы у нас был второй объект Person, который перезаписывал значение FavoriteColor.

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