JavaScript | Как создать свой Класс?

JavaScript | Как создать свой Класс?

В JavaScript уже имеется большое количество встроенных Классов, которые являются свойствами ГЛОБАЛЬНОГО объекта. Ты знаешь как они называются? Если нет, то погляди хотя бы на их названия — https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-well-known-intrinsic-objects. Так ты будешь в теме. Пройдя по этой ссылке ты узнаешь, что JavaScript на самом деле работает по стандарту ECMAScript. Именно поэтому ты нигде не найдёшь официальную документацию по JavaScript, потому что нужная тебе документация называется ECMAScript.

В JavaScript имеется возможность создавать свои собственные Классы. Овладеть этим навыком обязан каждый программист, который хочет создавать скрипты сложнее «Hello World!«.

 

Как создать самый примитивный класс Прямоугольника в JavaScript?

// Создание простого класса прямоугольника

 

class Pryamougolnik {   // название класса

    constructor(height, width){     // функция конструктор

        this.h = height;    // высота прямоугольника

        this.w = width;     // ширина прямоугольника

    }

}

Что тут что?

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

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

Если это непонятно, тогда давайте разберёмся на живом примере. Посмотрите в окно. Видите припаркованные автомобили? Я 100% уверен, что все автомобили должны иметь минимум 4 колеса, для того чтобы передвигаться по поверхности земли. Согласны? А ещё у всех автомобилей должен быть руль управления, педали газа и тормоза, сиденья … ну и в таком духе. То есть, когда я говорю слово Автомобиль, тогда вы точно понимаете, что это не Ноутбук или не Суп. В реальной жизни у каждого предмета есть свой набор характеристик. Чем сложнее предмет, тем больше в нём характеристик. Автомобиль тяжёлый, Ноутбук компактный, Суп горячий.

У каждого предмета реального мира могут меняться характеристики в зависимости от условий эксплуатации. Автомобиль перестал ездить потому что сломался двигатель. Ноутбук перестал загружаться потому что в нём вирус. Суп нельзя кушать потому что он 1 неделю простоял на балконе и скис.

Всю житейскую логику можно переложить на JavaScript. За текущую скорость автомобиля будет отвечать свойство объекта, а за изменением скорости будет отвечать метод этого объекта. Удобно же.

Вернёмся к прямоугольникам.

 

Второе слово, которое мы написали — это Pryamougolnik. Этим словом мы решили назвать наш собственный Класс.

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

 

Далее нужно указать Тело Класса — это две фигурные скобки { }. Внутри Тела Класса мы будем описывать наши будущие объекты прямоугольников.

 

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

Эта функция-конструктор так и называется — constructor. Она не может называться как-то по другому. Только так и никак иначе. Её оформление очень похоже на создание обычной функции. Мы также можем передавать параметры, а можем и не передавать. Главное в этой функции — это наличие ключевого слова this, которое обозначает «Этот Новый Созданный Прямоугольник«.

Выражение this.h = height говорит о том, что в новом созданном прямоугольнике-объекте из конструктора Класса будет в наличии свойство с ключом h. Этот ключ будет иметь значение, которое мы передали первым параметром в функцию. Если передадим 10, то h будет 10.

Выражение this.w = width аналогичным образом создаёт свойство с ключом w, значение которого передано вторым параметром в функцию-конструктор.

 

Как пользоваться своим созданным Классом Прямоугольника для создания нового объекта (экземпляра) в JavaScript?

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

Для создания нового экземпляра класса Pryamougolnik, нужно обязательно использовать оператор new:

// Как пользоваться классом Pryamougolnik?

// Как создать новый объект прямоугольника?

 

let a1 = new Pryamougolnik(1, 2)

Теперь у нас в переменной a1 лежит первый экземпляр Класса Pryamougolnik. Давайте на него посмотрим из консоли браузера:

Создали Класс Прямоугольника в JavaScript и создали первый экземпляр Класса
Создали Класс Прямоугольника в JavaScript и создали первый экземпляр Класса

 

Мы всего лишь передали два числа в конструктор Класса и на выходе получили объект, у которого прописались свойства с ключами h и w, а также значениями 1 и 2.

Ещё браузер нам подсказывает, что перед нами представитель класса Pryamougolnik, а не какой-то Array, String или Number.

Чтобы проверить к какому классу принадлежит наш объект, нам нужно выполнить команду.

// Получаем имя Класса,

// в котором создан объект a1

a1.constructor.name;

Получаем строку, которая хранит в себе имя Класса нашего прямоугольника — ‘Pryamougolnik’.

Получили имя класса Pryamougolnik через свойства constructor.name в строковом представлении в JavaScript
Получили имя класса Pryamougolnik через свойства constructor.name в строковом представлении в JavaScript

 

Зачем мы создали свой Класс Прямоугольника в JavaScript, если всё равно трудно решать задачу?

И вот мы подобрались к самому важному вопросу, касаемо Классов в JavaScript: «Зачем нужно создавать Классы?»

Давай представим, что нам нужно высчитывать площадь прямоугольника. Как в текущей ситуации мы можем это сделать?

  1. Мы можем также последовательно в коде умножать одно свойство на другое.
  2. Мы можем написать функцию в глобальной области видимости и передавать в неё наш объект прямоугольника.

Код:

// Мы можем также последовательно

// в коде умножать одно свойство на другое.

a1.h * a1.w

 

// Мы можем написать функцию в глобальной области видимости

// и передавать в неё наш объект прямоугольника.

function hw (obj){

   return obj.h * obj.w

}

Результат:

Перемножили два свойства объекта вручную и отдельной функцией в JavaScript
Перемножили два свойства объекта вручную и отдельной функцией в JavaScript

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

Проблема первого случая в том, что нам нужно будет каждый раз прописывать операцию перемножения, обращаясь к каждому свойству высоты и ширины каждого прямоугольника. Если прямоугольников будет 1000, то мы сломаемся и никогда вручную такое не напишем. Очень много нужно писать. Код будет не динамический, а статический. Если прямоугольников станет 10000, то нам нужно будет переписывать и пересчитывать площадь каждого заново. Это не вариант.

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

Так как же упростить разработку и правильно применить свой собственный Класс Прямоугольника для решения подобной задачи в JavaScript?

 

Польза от создания своего собственного Класса в JavaScript и от написания методов

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

Код Класса (обновлённый):

// Добавлен метод подсчёта площади прямоугольника

class Pryamougolnik{

 

    constructor(height, width){

        this.h = height;   // высота

        this.w = width;   // ширина

    }

 

    daiPloshad(){

        return this.h * this.w; // умножение ширины на высоту

    }

 

}

Мы просто добавили функцию daiPloshad(), которая также взаимодействует с ключевым словом this. Эта функция принадлежит своему прототипу (Классу Pryamougolnik)

Но на этот раз всё остальное иначе.

Создаём два объекта прямоугольника:

//

let p20 = new Pryamougolnik(30, 40);

let p21 = new Pryamougolnik(13, 19);

//

Скриншот из консоли:

Создали два объекта с классом Pryamougolnik в JavaScript
Создали два объекта с классом Pryamougolnik в JavaScript

И теперь посмотрим на них повнимательнее. Хорошо, что консоль браузера Google Chrome позволяет красиво отобразить состав объектов.

Два объекта класса Pryamougolnik унаследовали от своего прототипа метод вычисления площади в JavaScript
Два объекта класса Pryamougolnik унаследовали от своего прототипа метод вычисления площади в JavaScript

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

Оба объекта унаследовали от своего прототипа метод вычисления площади. Они знают куда нужно обратиться, чтобы вычислить площадь САМОГО СЕБЯ.

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

//

p20.daiPloshad(); // 1200

p21.daiPloshad(); // 247

//

Результаты:

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

Посмотрите как это коротко и понятно выглядит. Мы ничего визуально не перемножаем. Мы никуда не передаём объекты. Мы просто вызываем метод daiPloshad(), на нужном объекте при помощи точечного обращения.

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

 

Какие ещё плюсы можно получить от создания своего собственного Класса в JavaScript? Продолжаем улучшать класс.

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

Давайте теперь НАУЧИМ Класс вычислять диагональ прямоугольника:

// Добавлен метод подсчёта диагонали прямоугольника

 

// Либо зановго переобъявляем весь класс

class Pryamougolnik{

 

    constructor(height, width){

        this.h = height;    // высота

        this.w = width;     // ширина

    }

 

    daiPloshad(){

        return this.h * this.w; // умножение ширины на высоту

    }

 

    daiDiag(){

        // квадрат гипотенузы равен сумме квадратов катетов

        return Math.sqrt(this.h**2 + this.w**2);

    }

 

}

 

// Либо расширяем прототип одним методом

Pryamougolnik.prototype.daiDiag = function(){

    return Math.sqrt(this.h**2 + this.w**2)

}

Расширяем Класс и создаём новый объект:

Расширили класс прямоугольников новым методом вычисления диагонали в JavaScript
Расширили класс прямоугольников новым методом вычисления диагонали в JavaScript

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

//

let p22 = new Pryamougolnik(5, 8);

p22.daiPloshad();

p22.daiDiag();

//

Смотрим в консоли:

Получили площадь и диагональ прямоугольника используя методы собственного класса в JavaScript
Получили площадь и диагональ прямоугольника используя методы собственного класса в JavaScript

… и кажется что это всё, но ..

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

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

//

p20.daiDiag();

p21.daiDiag();

//

Как разработчики, мы теперь можем отключить голову в проблемах размещения функционала в коде. Мы можем спокойно добавлять новые реализации по манипулированию с объектами нашего класса. Они не выпрыгнут наружу и не смогут работать с методами других классов — вся логика работы надёжно ИЗОЛИРОВАНА.

Старые объекты также унаследовали новый метод вычисления диагонали из своего прототипа в JavaScript
Старые объекты также унаследовали новый метод вычисления диагонали из своего прототипа в JavaScript

Конечно же это не всё про классы. Это основа. Если вы поймёте зачем нужны Классы, то ваша разработка изменится. Изменится ваше мышление.

 

Информационные ссылки

Стандарт ECMAScripthttps://tc39.es/ecma262/multipage/