Классы в JavaScript

Ранее, до появления версии EcmaScript 6 классы в JavaScript реализовывались через создание функции-конструктора объектов. Эта функция и представляла собой класс. Она позволяла создавать приватные, публичные и статические члены класса без явного указания модификатора доступа.

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

Появление EcmaScript 6 изменил синтаксис создания классов в лучшую сторону. Стандарт позволил JavaScript программистам проектировать классы как это делается в большинстве ООП языках, через ключевое слово «class». При этом, старый стандарт никуда не делся.

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

Что такое классы?

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

Класс состоит из следующих элементов:

  • class Name{} — объявление класса через ключевое слово class, имя Name пишется с большой буквы и может быть произвольным — можно и с маленькой но заглавная буква ставится по правилам хорошего тона), а блок «{}» является границей описания класса;
  • публичные свойства — переменные, которые могут хранить примитивные значения, массивы, объекты и списки, доступ к свойствам осуществляется через имя объекта;
  • публичные методы — функции класса, которые, как и свойства, скрыты в объектах от глобального контекста;
  • приватные методы и свойства — не могут быть доступны напрямую через имя объекта, что вызовет ошибку, они доступны лишь на уровне класса, то есть — могут использоваться только публичными методами класса и помечаются модификатором «#»;
  • статические свойства и методы — обычные функции и переменные класса, объявленные с модификатором static, не являются экземплярами объектов, но класса, доступ к ним осуществляется через имя класса, а не объекта;
  • конструктор — является функцией-конструктором объектов, она может принимать различные параметры для редактирования свойств для различных объектов.

Пример объявления класса:

class Human{

}

Добавим свойства в наш класс:

class Human{
height: 180; // свойство
weight: 75;

// добавим метод
show_characteristics(){
alert(this.height+» «+this.weight);
}
}
// создадим объект

var Dmitry = new Human(); // создали объект, конструктором по умолчанию
alert(Dmitry.height); // 180 — доступ к свойству осуществляется через имя объекта
show_characteristics(); 180 75 — через имя объекта

Обратите внимание, что в теле метода присутствует слово this. Оно обозначает текущий объект, то есть — оно является заменой имени объекта. This — этот объект. К примеру, для объекта «Саши» и «Пети» свой this, один раз определенный в классе, но у каждого объекта this — имя переменной объекта. Кстати переменная, которая определяется при создании объекта является ссылкой на кучу — область памяти, где хранятся все объекты.

Определим в объекте конструктор

class Car{
model; // значения свойств будут определены конструктором
year;

constructor(a, b){
this.model = a;
this.year = b;
}
}

// Создадим объект через конструктор

var ford = new Car(«Ford», 2010);
alert(ford.model); // Ford
alert(ford.year); // 2010

// еще объекты
var lada = new Car(«Lada», 1990);
var volga = new Car(«Volga», 1980);

Приватные экземпляры класса

В EcmaScript 6 появилась простая возможность установить приватность методов и свойств. Для этого достаточно поставить символ «#» перед именем метода или свойства без пробела: #someMethod(){}, #someProperty = 12. Приватные свойства или методы не могут быть доступны через имя объекта или класс. Они доступны только в контексте класса. Поэтому их используют внутри публичных или статических методов.

Пример:

class Device{
width;
#height; // объявили приватное свойство
constructor(a, b){
this.width = a;
this.height = b; // задаем значение приватному свойству через конструктор
}
show_info(){
alert(this.height); // выводим значение приватного свойства
}
}

// создадим объект и проверим как можно получить значение приватного свойства

var phone = new Device(10, 20);
alert(phone.width); // 10 — ничего не произошло, значение вывелось без проблем
alert(phone.height); // ошибка! — нельзя получить доступ к приватному свойству через имя объекта
phone.show_info(); // 20 — значение приватного свойства выведено через публичный метод

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

Пример:

class Device{
width;
height;
constructor(a, b){
this.width = a;
this.height = b;
}
#show_info(){ // создали приватный метод
alert(this.height);
}

get_info{ // публичный метод-обертка, который вызывает приватный метод
this.show_info();
}
}

var tablet = new Device(100, 200);
tablet.show_info(); // Ошибка! Приватный метод нельзя вызвать напрямую через объект
tablet.get_info(); // 200 — вызов публичного метода активировал вызов приватного метода и ошибки никакой нет

Статические свойства и методы

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

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

Пример:

class Device{
width;
height;
type;
static electric_count = 0; // счетчик электрических чайников
static common_count = 0; // счетчик электрических чайников
constructor(a, b, t){
this.width = a;
this.height = b;
this.type = t; // третий аргумент указывает тип чайника: электрический или обычный
if(this.t==»electric») Device.electric_count++; // если тип созданного объекта чайника является электрическим, то их счет увеличивается на один
else Device.common_count++; // если не электрический то счетчик простых увеличивается на один
}

// Теперь протестируем наши статические свойства на объектах

var phillips = new Device(20, 50, «electric»);
var samsung = new Device(21, 51, «electric»);
var common = new Device(23, 51, «common»);

console.log(phillips.electric_count); // Ошибка! Доступ к статическому экземпляру осуществляется только через имя класса
console.log(Device.electric_count); // 2 — было создано два электрочайника
console.log(Device.common_count); // 1 — обычных чайников было создано всего один

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

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

Какие еще есть возможности в ООП в JavaScript

Стоит отметить, что JavaScript до версии ES6 был прототипно-ориентированным языком программирования, а классы создавались благодаря функциям-конструкторам. Новый стандарт 2015-го года сделал язык более приближенным к ООП. Появление классов и модификаторов доступа позволило JS с легкостью реализовать такие приемы ООП как: наследование, полиморфизм, инкапсуляция.

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

ООП подарило для JavaScript возможность явно указывать модификаторы доступа для свойств и методов. Когда в функциональном стиле отделить члены класса было достаточно непросто — нужно было писать простые функции или вложенные.

Наследование также реализовывалось не совсем по людски. При копировании свойств и методов из основного класса требовалось писать непонятную конструкцию. В новом стиле JS все решает простой метод super().

Классы позволяют забыть о сложности изучения прототипов. Однако не рекомендуется тем, кто собирается программировать на JS или строить карьеру, забывать о прототипах. В серьезных проектах, потребуется знание полного языка, а не только обновлений 2015-го года. При том, что JavaScript является динамически-типизированным языком (не нужно явно указывать тип переменных), то программист избавляется от таких сложностей, как преобразование типов различных объектов, а также перегрузок операций над преобразованием типов.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *