Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як додати метод у класі». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Метод додають прямо в тілі класу записом `name() {}`, і він автоматично потрапляє у `Class.prototype`, тобто стає спільним для всіх екземплярів.** Крім звичайного методу є ще чотири варіанти: `static name() {}` для методу самого класу, пара `get name() {}` / `set name(v) {}` для доступу під виглядом властивості, `#name() {}` для справді приватного методу і поле зі стрілкою `name = () => {}`, яке прив'язує `this` до екземпляра. Метод можна також дописати вже після оголошення класу через `Class.prototype.name = function () {}`, бо `class` під капотом це функція з прототипом. **Ключове:** звичайні методи живуть у прототипі й спільні для всіх об'єктів, а поля-стрілки створюються заново на кожен екземпляр, зате не втрачають `this`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Метод у класі додають, просто записавши його в тілі класу: `greet() { ... }`, після чого він потрапляє у прототип і стає доступним усім екземплярам.** Крім звичайного методу JavaScript дає статичні методи, геттери та сеттери, приватні методи з `#` і поля-методи зі стрілковою функцією, і кожен варіант вирішує свою задачу. ## Теорія ### TL;DR - Звичайний метод `m() {}` у тілі класу потрапляє у `Class.prototype` і спільний для всіх екземплярів. - Метод можна дописати й після оголошення класу: `Class.prototype.m = function () {}`. - `static m() {}` належить самому класу, екземпляри його не бачать. - `get` і `set` дають доступ під виглядом звичайної властивості. - `#m() {}` це справді приватний метод, доступний лише зсередини класу. - Поле-стрілка `m = () => {}` не втрачає `this`, тому зручне для колбеків. ### Швидкий приклад ```javascript class User { constructor(name) { this.name = name; } greet() { console.log(`Hi, ${this.name}!`); } } const u = new User("Alice"); u.greet(); // Hi, Alice! ``` ### Звичайний метод і додавання методу пізніше Звичайний (публічний) метод доступний у всіх екземплярів класу: ```javascript class User { constructor(name) { this.name = name; } greet() { console.log(`Hi, ${this.name}!`); } } const u = new User("Alice"); u.greet(); // Hi, Alice! ``` Такі методи автоматично додаються в `User.prototype`, тобто розділяються всіма екземплярами, а не створюються заново для кожного об'єкта. Метод можна додати у прототип класу і вже після оголошення, вручну: ```javascript class User { constructor(name) { this.name = name; } } // Додаємо метод пізніше User.prototype.sayBye = function () { console.log(`${this.name} says: bye!`); }; const u = new User("Alice"); u.sayBye(); // Alice says: bye! ``` Це працює тому, що під капотом `class` це просто функція з `prototype`. Різниця в деталі: доданий вручну метод буде перелічуваним, тоді як методи з тіла класу, ні. ### Статичний метод Такий метод викликається безпосередньо на класі, а не на екземплярі: ```javascript class MathUtils { static square(n) { return n * n; } } console.log(MathUtils.square(5)); // 25 ``` > Екземпляри (`new MathUtils()`) не мають доступу до `static`-методів. ### Геттер і сеттер Використовуються, щоб «замаскувати» властивості під методи і контролювати доступ до них: ```javascript class Product { constructor(price) { this._price = price; } get price() { return this._price + " USD"; } set price(value) { if (value < 0) throw new Error("Price cannot be negative"); this._price = value; } } const p = new Product(1000); console.log(p.price); // "1000 USD" p.price = 1500; console.log(p.price); // "1500 USD" ``` > Під час читання `p.price` фактично викликається `get price()`, а під час присвоєння `p.price = ...` викликається `set price()`. ### Приватні методи і поля-методи зі стрілкою Приватні методи з решіткою недоступні ззовні, тільки всередині класу: ```javascript class Account { #logBalance() { console.log(`Current balance: ${this.balance}`); } constructor(balance) { this.balance = balance; this.#logBalance(); // викликати можна лише звідси } } const acc = new Account(500); // acc.#logBalance(); -> помилка, це приватний метод ``` Якщо ж треба, щоб метод зберігав контекст `this`, його оголошують як поле зі стрілковою функцією: ```javascript class Button { label = "Click me"; handleClick = () => { console.log(`Clicked: ${this.label}`); }; } const b = new Button(); b.handleClick(); // Clicked: Click me ``` Такі методи не втрачають `this`, навіть якщо передати їх як колбек: ```javascript setTimeout(b.handleClick, 1000); // усе працює коректно ``` Плата за це: поле-стрілка створюється окремо для кожного екземпляра і не лежить у прототипі. ### Підсумкова таблиця | Тип методу | Синтаксис | Доступність | Особливості | | --- | --- | --- | --- | | Звичайний | `method() {}` | Через екземпляр | Спільний для всіх екземплярів | | Статичний | `static method() {}` | Через сам клас | Не видно на екземплярах | | Геттер / сеттер | `get name() {}`, `set name(v) {}` | Як властивість | Дозволяє контролювати доступ | | Приватний | `#method() {}` | Лише всередині класу | Повна інкапсуляція | | Поле-метод (стрілка) | `method = () => {}` | Через екземпляр | Не втрачає `this` | ### Типові помилки - Ставити кому або крапку з комою між методами в тілі класу: це не об'єктний літерал, роздільники там не потрібні. - Робити всі методи полями-стрілками «щоб не думати про `this`»: так кожен екземпляр отримує власні копії функцій і виграш прототипу зникає. - Викликати `static`-метод на екземплярі та отримувати `TypeError`. - Називати геттер так само, як поле (`get price()` і `this.price = ...` у конструкторі): вийде нескінченна рекурсія, тому у прикладі поле і назване `_price`. - Забувати, що `#`-методи не видно навіть у нащадках: приватність у класах працює по класу, а не по ланцюжку прототипів.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.