Основы ООП JS: подробно для всех

Объектно-ориентированное программирование – это популярный на сегодняшний день способ создания программных продуктов. Его миссия – упростить написание, чтение и работу с кодом. Эту парадигму поддерживают множество языков: C#, C++, Cyclone, Groovy, Io, Java, Objective-C, Perl, PHP, Python, Ruby, Scala и другие. Ну а как же насчет JavaScript? Хотя он также относится к объектно-ориентированным языкам, программирование ООП в JS происходит по-другому, со своими особенностями. В этой статье мы разберем, что такое ООП JS, как реализуются принципы парадигмы в этом языке и чем отличается процесс разработки.

Парадигма ООП JS

Прежде чем приступить к разбору JavaScript ООП, для начинающих стоит напомнить, что из себя представляет объектно-ориентированное программирование.

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

Реализация ООП на JS происходит через прототипы (функции-конструкторы). По этой причине многие эксперты считают JavaScript не самым объектно-ориентированным языком. Ведь по сути объектом считается всё в JS (классы ООП в том числе). Поэтому прототипирование – оптимальный способ добиться решения задач на ООП JS. Таким образом, JavaScript больше подходит название «прототипно-ориентированный». 

Объектно-ориентированное программирование строится на четырех основных принципах:

  • наследование;
  • инкапсуляция;
  • абстракция;
  • полиморфизм.

Из-за особенностей JavaScript реализация этих принципов также отличается.

Принципы ООП JS

Подробное описание сути принципов объектно-ориентированного программирования есть в другой нашей статье, так что не будем повторяться и поговорим конкретно об ООП принципах в JS.

Начнем с основного различия – наследование. В классическом варианте классы-потомки наследуют свойства и методы класса-родителя, дополняя их своими характеристиками по необходимости.

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

Что интересно, в ООП JS ES6, появилась реализация, приближенная к стандартной: создание родителя через class. Тем не менее то, что мы получаем, не считается традиционным классом, а служит лишь синтаксическим сахаром. То есть мы все равно продолжаем работать с функциями-конструкторами. По этой причине также некоторые характеризуют рассматриваемую парадигму в JavaScript как «JS ООП в функциональном стиле». 

Теперь перейдем к инкапсуляции. Модификаторов доступа private, public и protected в языке нет за счет отсутствия классов. Ранее по договоренности для объявления приватности добавлялось нижнее подчеркивание «_». Но это решение считалось весьма спорным.

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

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

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

Полиморфизм в предполагает следующее: методы родительского объекта (прототипа) наследуются дочерними, но реализация этих методов в зависимости от свойств того или иного объекта будет отличаться. Чтобы объяснить полиморфизм в JavaScript ООП для начинающих, приведем простой пример. Допустим, наш прототип (конструктор) – животное. У него есть описанные свойства (отряд, размер, место обитания и пр.), а также методы (плавает, летает, издает звуки). Возьмем последний метод – воспроизведение звуков: реакция кошки на него будет одна, а собаки – другая. То есть метод один и тот же, а реализация разная.

Ну что ж, давайте рассмотрим теперь ООП JS на примерах.

JavaScript ООП. Примеры

Итак, мы уже обсудили момент, что вместо классов в JavaScript используются прототипы (конструкторы).

Они как раз и дают абстрактное описание, шаблон будущих объектов.
Правила создания функции-конструктора:

  1. Имя с заглавной буквы.
  2. Вызов функции – через оператора new.

В работе с конструкторами и объектами используется ключевое слово this. Его значение зависит от контекста применения. С помощью this мы обращаемся к чему-либо.
Приведем по ООП JS примеры. Создадим конструктор Person, определим его свойства и методы, а затем добавим новый объект:

console.log('*** PERSON ***');

function Person (name) {

this.name = name;

}

Person.prototype = {

eyes: 2,

mouth: 1,

sleep: function () {

return 'zzz';

}

};

// создание человека (Person)

const p1 = new Person('John');

// прописываем:

console.log(

 `name: ${p1.name}`,

 `eyes: ${p1.eyes}`,

 `mouth: ${p1.mouth}`,

p1.sleep()

);

Чтобы создать на основе «класса» конструктор Employee, наследуем его свойства и добавим нужные характеристики (заработная плата), убрав лишние:

function Employee (name, salary) {

 this.name = name;

 this.salary = salary;

}

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

Employee.prototype = Object.create(Person.prototype);

Employee.prototype.constructor = Employee; // Устанавливаем его конструктор

// Повторяем то же самое

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

const em1 = new Employee('Jack', 2500);

// и прописываем:

console.log(

 `name: ${em1.name}`,

 `salary: ${em1.salary} USD`,

 `eyes: ${em1.eyes}`,

 `mouth: ${em1.mouth}`,

em1.sleep()

);

В ES6 создание конструктора происходит через class, а наследование будет выглядеть проще:

class Employee extends Person {

 constructor (name, salary) {

super(name);

this.salary = salary;

 }

}

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

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

Из новинок:

  1. Megane Noel «JavaScript for Beginners: A Complete Guide to Learn the Fundamentals of JavaScript and Start Programming Today!» (вторая книга из серии «Computer Programming», ноябрь, 2021).
  2. David Flanagan «JavaScript: The Definitive Guide: Master the World’s Most-Used Programming Language» (июнь, 2020).
  3. Cay Horstmann «Modern JavaScript for the Impatient» (июль, 2020).
  4. Adam D. Scott , Matthew MacDonald «JavaScript Cookbook: Programming the Web» (август, 2021).
  5. Rob Miles «Begin to Code with JavaScript» (август, 2021).

Также рекомендуем книгу автора Douglas Crockford «How JavaScript Works», которая есть и на русском языке (Дуглас Крокфорд «Как устроен JavaScript»). Выпущена она еще в 2018 году, но именно здесь автор уделяет много внимания вопросу: почему парадигма реализована в этом языке именно так. Методы взаимодействия JavaScript с объектно-ориентированным программированием подробно описаны к работе авторов Ved Antani и Stoyan Stefanov «Object-Oriented JavaScript: Learn everything you need to know about object-oriented JavaScript» (3-е издание, январь, 2017).

Да, JavaScript является ООП языком. Но принцип реализации этой парадигмы на JS несколько иной. В основе объектно-ориентированного программирования лежат классы и объекты. Но объектами в JavaScript считается всё, поэтому создать шаблон (класс) не получится, ведь он тоже станет объектом. Поэтому ООП в JS основывается не на классовом, а на прототипном наследовании. Создается обобщенный объект-родитель, где прописываются нужные свойства и методы, а уже от него производятся другие объекты.

Объект – самостоятельная единица, которая состоит из методов и свойств. Каждый из них содержит имя и значение. Свойства – это характеристики объекта, а методы – поведение. Объект – основной вид данных в языке JS. Любое значение в JavaScript (если это не строка, число или логическое значение) – это объект. Но даже то, что указано в скобках, может вести себя как неизменяемые объекты. Исходя из этой особенности ООП основывается в JS не на классах, а на прототипах. Чтобы создать ряд объектов, используется конструктор – обобщенный объект, где прописаны основные свойства для потомков. 

Да, объектно-ориентированное программирование важно в JavaScript. Когда вы разрабатываете небольшую программу самостоятельно, то применять ООП не имеет никакого смысла. Но если это крупный проект, то использование этой парадигмы решит ряд проблем: поддерживать, изменять и расширять существующий код будет гораздо проще. Благодаря прототипному наследованию, которое считается особенностью JS ООП, программирование становится более динамичным и гибким. Это особенно важно, когда над программой работает группа разработчиков.

Существует два способа создать объект в JavaScript.

Первый способ:

var obj = new Object({'name':'Alex'});

Это объект с одним свойством name, которое имеет значение «Alex».

Второй (сокращенный) способ:

var obj = {'name':'Alex'};

Если необходимо указать несколько свойств, между ними ставятся разделители – запятые:

var obj = {

'name': 'Alex',

'lastname': 'Ivanov'

};

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

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

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

 

error: Контент защищен.