Уроки JavaScript – ознайомлення з класами (частина 1)

Класи в JavaScript є однією з найпопулярніших функцій, і сьогодні ми зробимо їх короткий огляд. Ми розглянемо такі частини і концепції, як конструктор, властивості і методи класу, успадкування, суперклас і підкласи, а також способи перевизначення властивостей і методів конструктора і класу.

 

 

Створення об’єктів по-старому (за допомогою конструкторів функцій)

Як розробники створювали об’єкти до введення класів в JavaScript? Вони використовували конструктори функцій. Потім, коли потрібно було додати деякі властивості або методи до об’єкта, вони використовували один з двох способів.

По-перше, за допомогою ключового слова this прямо в конструкторі.

А по-друге? Можна додавати властивості або методи до об’єкта поза конструктора. В цьому випадку потрібно використовувати прототип об’єкта. Коли вам потрібно створити новий екземпляр об’єкта, ви визначаєте його як нову змінну і використовуєте ключове слово new, за яким слідує ім’я об’єкта і круглі дужки. Наприклад, let myInstance = new MyObj().

 

Тепер давайте перейдемо до практики.

Для початку давайте створимо новий об’єкт Person з чотирма властивостями: ім’ям, віком, ростом, вагою. В об’єкті будемо використовувати один метод (крок 1). Далі, створимо два примірника цього об’єкта з деякими властивостями (крок 2).

Якщо нам пізніше потрібно додати властивість до всіх екземплярів Person, ми можемо зробити це або всередині конструктора, або ж поза ним, використовуючи об’єкт-прототип.

Щоб додати додатковий метод до об’єкта Person, використовуйте прототип об’єкта. Як і у випадку з новою властивістю, всі екземпляри також автоматично успадковують цей метод (крок 5).

<script>   // Крок 1: Використовуємо конструктор функції для створення об'єкта Person   function Person(name, age, height, weight) {   // Додаємо властивості об'єкта за замовчуванням, використовуючи this   // this відноситься до об'єкту Person    this.name = name;    this.age = age;    this.height = height;    this.weight = weight;    // Додаємо метод для отримання властивості name    this.getName = function() {    // Використовуємо ключове слово this для посилання на властивість name об'єкта Person     return this.name;    }   }   // Крок 2: Створюємо два примірника об'єкта Person, ivanov та petrov   let ivanov = new Person('Іванов', 25, 195, 105);   let petrov = new Person('Петров', 30, 180, 72);   console.log(ivanov.getName()) // Вивід: Іванов   console.log(petrov.getName()) // Вивід: Петров   // Крок 3: Додаємо властивість статі тільки примірнику ivanov та виводимо її   ivanov.gender = 'чоловічий';   console.log(ivanov.gender); // Вивід: чоловічий   // при спробі записати стать для примірника petrov, вивід буде undefined, оскільки властивість «gender» є тільки в примірнику ivanov   // Крок 4: Використання прототипу об'єкта для додавання властивості статі в об'єкт Person   Person.prototype.gender = 'some gender';   // пробуємо знову записати стать для примірника petrov   console.log(petrov.gender); // Вивід: 'some gender'   // Причина: додавання «gender» до прототипу Person автоматично додало його в усі екземпляри   // Крок 5: Використання прототипу об'єкта для додавання методу, щоб отримати властивість age для прототипу об'єкта Person   Person.prototype.getAge = function () {    // this відноситься до об'єкта Person    return this.age;   }   // отримуємо вік ivanov та petrov   console.log(ivanov.getAge()) // 25   console.log(petrov.getAge()) // 30  </script>  

 



 

Створення об’єктів по-новому (з класами JavaScript)

Хоча класи в JavaScript можуть виглядати як щось абсолютно нове, під капотом все ще зберігаються конструктори функцій. Є тільки трохи нових відмінностей.

Давайте тепер перепишемо попередній приклад за допомогою класу JavaScript. Як бачите, єдина відмінність полягає на першому етапі. Тут ми визначили Person як клас. Властивості, які ми хочемо передати в якості аргументів при створенні нового екземпляра, тепер визначаються за допомогою конструктора класів. Також зверніть увагу на відсутність this, коли ми визначаємо метод getName().

Все інше в основному те ж саме і працює так само, як і раніше. Це відноситься і до того, як ви створюєте нові екземпляри. Ви як і раніше використовуєте змінні разом з ключовим словом new і ім’ям об’єкта (тепер класу).

<script>   // Використання класу JavaScript для створення об'єкта Person   class Person {    constructor(name, age, height, weight) {    // Додаємо властивості об'єкта за замовчуванням     this.name = name;     this.age = age;     this.height = height;     this.weight = weight;    }    // Додаємо метод для отримання властивості name    getName() {     return this.name;    }   }  </script>  

 

 

 

Конструктор в JavaScript

Одна із загальних рис класів JavaScript – це метод конструктора. Це особливий метод в класі. Це метод, який створює та ініціалізує об’єкт, створений за допомогою класу. Це означає, що кожен раз, коли ви створюєте новий екземпляр класу, JavaScript автоматично викликає метод конструктора.

У кожного класу може бути тільки один конструктор. Типове використання конструктора – створення властивостей класу за замовчуванням. Потім ви можете передати ці властивості при створенні нових екземплярів класу. Або ви можете оголосити їх з деякими значеннями за замовчуванням.

Метод конструктора не є обов’язковим. Ви можете визначити класи за допомогою конструктора (Приклад 1) або без нього (Приклад 2).

Якщо ви включаєте конструктор в клас, ви повинні визначити його на самому початку класу, вгорі коду класу. В іншому випадку JavaScript видасть помилку.

 

Приклад 1: Клас з використанням конструктора

<script>   class MyClass {    // Використовуємо конструктор для додавання властивостей класу    constructor(message = 'Hello world!') {     this.message = message;    }    // Додаємо метод класу    printMessage() {     return this.message;    }   }   // Створюємо екземпляр класу MyClass   const instanceOfMyClass = new MyClass();   console.log(instanceOfMyClass.printMessage()); // Вивід: 'Hello world!'  </script>  

 

 

Приклад 2: Клас без використання конструктора

<script>   class MyClass {    // Додаємо метод класу    printMessage() {     return 'Hello world!';    }   }   // Створюємо екземпляр класу MyClass   const instanceOfMyClass = new MyClass();   console.log(instanceOfMyClass.printMessage()); // Вивід: 'Hello world!'  </script>  

 

 

 

Властивості і методи класу

Атрибути і поведінка в класах JavaScript називаються властивостями класу і методами класу. Ви вже бачили їх приклади вище.

Коли ви хочете додати властивість в клас, ви робите це в методі конструктора.

Коли ви хочете додати метод, ви робите це всередині класу, але поза конструктором.

Коли ви хочете послатися на будь-яку властивість або метод всередині класу, ви повинні використовувати ключове слово this.

 

Давайте створимо клас NewClass з двома властивостями, classPropOne і classPropTwo, і двома методами, someClassMethod і anotherClassMethod.

<script>   // Створюємо новий клас під назвою MyClass   class NewClass {    // Додаємо дві властивості класу, classPropOne і classPropTwo    constructor(classPropOne, classPropTwo) {     this.classPropOne = classPropOne;     this.classPropTwo = classPropTwo;    }    // Додаємо метод класу з ім'ям someClassMethod    someClassMethod() {     return this.classPropOne;    }    // Додаємо метод класу з ім'ям anotherClassMethod    anotherClassMethod() {     return this.classPropTwo;    }   }  </script>  

 

 

Працювати з класами JavaScript, їх властивостями і методами дуже просто. Ви можете побачити це в прикладі на самому початку цієї статті, але це варто згадати ще раз. Ви також можете додати нові властивості і методи в класи JavaScript пізніше, не вносячи змін безпосередньо в визначення класу.

Ви можете зробити це за допомогою об’єкта-прототипу. Це працює як з властивостями класу, так і з методами. Синтаксис простий. По-перше, це назва класу. Далі слідує ключове слово prototype, за яким слідує ім’я методу або властивості, з крапками між ім’ям класу прототипу та ім’ям методу або властивості.

<script>   // Додаємо новий метод з ім'ям newClassMethod в клас NewClass   NewClass.prototype.newClassMethod = function() {    return this.classPropOne + ' та ' + this.classPropTwo;   }   // Створюємо примірник NewClass під назвою foo   let foo = new NewClass('foo', 'bar');   console.log(foo.newClassMethod()); // Вивід: 'foo та bar'  </script>  

 

 

 

Успадкування класу (розширення)

Тепер давайте поговоримо про спадкування або розширення класів. Розширення класів в основному означає, що ви створюєте один клас, дочірній клас або підклас на основі іншого класу, батьківського класу або суперкласу. Дочірній клас або підклас успадковує властивості і методи від батьківського класу або суперкласу.

Основною перевагою цього є те, що ви можете додати функціональність без зміни вихідного класу. Це особливо важливо, коли ви не хочете змінювати екземпляри цього класу. Якщо ви додасте функціональність в клас за допомогою прототипу, будь-яка зміна, яку ви зробите в класі, буде автоматично поширюватися на всі його екземпляри.

Уявіть, що у вас є клас під назвою Vehicle. Цей клас має деякі властивості, такі як назва, стан і швидкість. Тепер припустимо, що ви хочете використовувати цей клас для створення екземпляра не тільки автомобіля, але й, наприклад, літака. Всі ці транспортні засоби можуть мати специфічні для них властивості, такі як кількість коліс, потужність двигуна і т.д.

Перший спосіб – додати всі ці властивості в клас Vehicle. Проблема полягає в тому, що це захаращує всі екземпляри класу Vehicle властивостями або методами, які вони ніколи не будуть використовувати. Інший, і набагато кращий, варіант – використовувати успадкування. Це означає, що ви створите підкласи для автомобіля і літака, використовуючи Vehicle як суперклас.

Це дозволить вам додавати певні властивості тільки до класів або підкласів, які будуть їх використовувати. Більш того, оскільки всі ці нові класи будуть підкласами суперкласу Vehicle, всі вони зможуть використовувати деякі властивості і методи, успадковані від Vehicle.

Спосіб створення підкласів суперкласу або розширення класів простий. Ви оголошуєте клас як зазвичай, але додаєте extends та ім’я суперкласу між ім’ям класу та фігурними дужками. Наприклад, class MySubclass extends SuperClass{}. Потім ви можете додати властивості і методи, так, ніби ви використовуєте звичайний клас.

<script>   // створюємо суперклас Vehicle   class Vehicle {    constructor(name, condition, speed) {     this.name = name;     this.condition = condition;     this.speed = speed;    }   }   // створюємо підклас Car   class Car extends Vehicle {    constructor(name, condition, speed, numOfWheels) {     // Викликаємо функцію super() з усіма параметрами, необхідними для класу Vehicle     super(name, condition, speed);     this.numOfWheels = numOfWheels;    }    // Додаємо метод для виводу всіх властивостей    printInfo() {     return `Назва: ${this.name}, Стан: ${this.condition}, Макс. швидкість: ${this.speed}, Коліс: ${this.numOfWheels}`;    }   }   // Створюємо екземпляр класу Car   const tesla = new Car('Tesla', 'новий', 280, 4);   console.log(tesla.printInfo()); // Вивід: 'Назва: Tesla, Стан: новий, Макс. швидкість: 280, Коліс: 4'  </script>  

 

 

 

Успадкування та дочірні класи (або підкласи)

Одна річ, яку ви повинні знати про спадкування. Це не обмежено суперкласами. Ви також можете дозволити одному підкласу успадковувати від іншого підкласу, який також може успадковувати від ще одного підкласу, який може успадковувати від суперкласу. В крайньому випадку, ви можете створити ланцюжок з сотень підкласів, які успадковують один від іншого, з одним суперкласом вгорі.

 

 

Перевизначення конструктора класу

Як ви могли бачити в прикладах вище, всі підкласи мали свій власний метод конструктора. Це означає, що вони перевизначають конструктор суперкласу. Коли це відбувається, коли підклас перевизначає конструктор суперкласу, ви повинні викликати метод super() з усіма початковими параметрами конструктора.

Виклик super() всередині конструктора викликає конструктор суперкласу, в даному випадку – Vehicle. Це дозволяє підкласам використовувати властивості, визначені в конструкторі суперкласу. Важливо пам’ятати, що вам потрібно викликати метод super() в самій верхній частині конструктора.

Ви повинні викликати його перед тим, як додавати будь-які властивості. Якщо ви забудете про це, ключове слово this та його посилання на клас не існуватимуть, і JavaScript видасть помилку. Якщо у підкласу немає власного конструктора, тоді вам не потрібно турбуватися ні про конструктор суперкласу, ні про super().

 

 

Продовження в другій частині.