====== Класи ====== ===== Оголошення класу ===== class User { // Тіло класу } ===== Екземпляра класу ===== class User { // Тіло класу } const mango = new User(); console.log(mango); // {} const poly = new User(); console.log(poly); // {} ===== Конструктор класу ===== * Якщо метод конструктора (constructor) не визначити в явному вигляді, то буде створений конструктор за замовчуванням — порожня функція, яка не змінює екземпляр класу. * Виклик класу з оператором new призводить до створення нового об'єкта й автоматичного виклику методу constructor * Аргументи, які передаються при виклику new User(), стають значеннями параметрів для методу constructor. * метод constructor викликається в контексті створюваного екземпляра. class User { constructor(name, email) { console.log(name, email); } } const mango = new User("Mango", "mango@mail.com"); // "Mango mango@mail.com" console.log(mango); // {} class User { constructor({ name, email }) { this.name = name; this.email = email; } } const mango = new User({ name: "Mango", email: "mango@mail.com", }); console.log(mango); // { name: "Mango", email: "mango@mail.com" } ===== Методи класу ===== це функції, які будуть доступні екземпляру в його прототипі. Вони оголошуються в довільному порядку після конструктора. На відміну від синтаксису методів об'єкта (вони розділяються комою), методи класу не розділені жодними спеціальними символами. * Методи класу додаються до спеціального об'єкта, який зберігається у властивості prototype самого класу. * class User { constructor({ name, email }) { this.name = name; this.email = email; } getEmail() { return this.email; } changeEmail(newEmail) { this.email = newEmail; } } ===== Приватні властивості ===== Додаючи до імені властивості на початку символ #, ми робимо її приватною. О__голошення приватної властивості до ініціалізації в конструкторі є обов'язковим__. class User { // Необов'язкове оголошення публічних властивостей name; // Обов'язкове оголошення приватних властивостей #email; constructor({ name, email }) { this.name = name; this.#email = email; } } const mango = new User({ name: "Mango", email: "mango@mail.com", }); console.log(mango.name); // "Mango" console.log(mango.#email); // Виникне помилка, це приватна властивість ===== Приватні методи ===== class User { name; #email; constructor({ name, email }) { this.name = name; this.#email = email; } // Публічний метод для отримання електронної пошти getEmail() { return this.#email; } // Публічний метод для зміни електронної пошти changeEmail(newEmail) { this.#email = newEmail; } } const mango = new User({ name: "Mango", email: "mango@mail.com", }); console.log(mango.getEmail()); // "mango@mail.com" mango.changeEmail("mango@supermail.com"); console.log(mango.getEmail()); // "mango@supermail.com" ===== Статичні властивості ===== Властивості, що доступні тільки класові, але не його екземплярам — це статичні властивості. class MyClass { static myProp = "value"; } console.log(MyClass.myProp); // "value" ===== Статичні методи ===== У класі можна оголосити не тільки методи майбутнього екземпляра, а й статичні методи. Статичні методи — це методи, доступні тільки класу. Вони можуть бути публічні та приватні. class User { static #takenEmails = []; static isEmailTaken(email) { return User.#takenEmails.includes(email); } #email; constructor({ email }) { this.#email = email; User.#takenEmails.push(email); } } const mango = new User({ email: "mango@mail.com" }); console.log(User.isEmailTaken("poly@mail.com")); // false console.log(User.isEmailTaken("mango@mail.com")); // true ===== Геттери і сеттери ===== * Элемент ненумерованного спискаце спеціальний синтаксис оголошення методів для взаємодії з властивостями. Геттер і сеттер імітують звичайну публічну властивість класу, але дозволяють взаємодіяти з іншими властивостями зручнішим способом. * Перевага в тому, що це методи. Отже, під час запису або читання можна виконати додатковий код з будь-якими перевірками, на відміну від виконання цієї ж операції безпосередньо з властивістю. * Геттер і сеттер повинні називатися однаково. Краще називати геттери і сеттери так само, як і властивість, з якою вони працюють. Геттер може існувати без сеттера, так само як і сеттер без геттера. class User { #email; constructor({ name, email }) { this.name = name; this.#email = email; } // Геттер email get email() { return this.#email; } // Сеттер email set email(newEmail) { this.#email = newEmail; } } * Звертаючись до mango.email, викликається геттер get email() {...} і виконується його код. * При спробі запису mango.email = "mango@supermail.com" викликається сеттер set email(newEmail) {...}, і рядок "mango@supermail.com" буде значенням параметра newEmail. const mango = new User({ name: "Mango", email: "mango@mail.com" }); console.log(mango.email); // mango@mail.com mango.email = "mango@supermail.com"; console.log(mango.email); // mango@supermail.com ===== Наслідування класів ===== **extends** дозволяє реалізувати наслідування класів, коли один клас (дочірній, похідний) наслідує властивості й методи іншого класу (батьківського). class Parent {} class Child extends Parent { // ... } ===== Конструктор дочірнього класу ===== super(args) — це псевдонім конструктора батьківського класу. class User { #email; constructor(email) { this.#email = email; } get email() { return this.#email; } set email(newEmail) { this.#email = newEmail; } } class ContentEditor extends User { constructor({ email, posts }) { super(email); // Виклик конструктора батьківського класу User this.posts = posts; } } const editor = new ContentEditor({ email: "mango@mail.com", posts: [] }); console.log(editor); // { #email: "mango@mail.com", posts: [] } console.log(editor.email); // "mango@mail.com" ===== Методи дочірнього класу ===== Дочірній клас може використовувати методи та властивості батьківського класу. Крім цього, у дочірньому класі можна оголошувати методи, які будуть доступні тільки його екземплярам. // Уявімо, що вище є оголошення класу User class ContentEditor extends User { constructor({ email, posts }) { super(email); this.posts = posts; } addPost(post) { this.posts.push(post); } } const editor = new ContentEditor({ email: "mango@mail.com", posts: [] }); console.log(editor); // { #email: "mango@mail.com", posts: [], addPost: f } editor.addPost("post-1"); editor.addPost("post-2"); console.log(editor.posts); // ['post-1', 'post-2'] У прикладі бачимо, що ContentEditor успадковує клас User. * User — це базовий клас, який має приватну властивість #email. * ContentEditor розширює клас User і має власну властивість posts. Клас ContentEditor також має метод addPost, який дозволяє додавати нові повідомлення до posts.