Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Ключове слово static у класах». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`static` робить властивість або метод частиною самого класу, а не його екземплярів: звертатися до них треба через ім'я класу (`User.role`), а не через об'єкт (`u.role` дасть `undefined`).** Усередині статичного методу `this` вказує на клас, тому статика може викликати іншу статику. Під час `extends` статичні члени успадковуються. ```javascript class User { static role = 'Користувач'; static createGuest() { return new User('Гість'); } constructor(name) { this.name = name; } } User.role; // 'Користувач' new User('Maria').role; // undefined ``` **Ключове:** статика, це спільні для всього класу дані й утиліти (фабрики, константи, лічильники), а не стан окремого об'єкта.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`static` робить властивість або метод частиною класу, а не частиною його екземплярів.** Це ідеальний інструмент для спільних функцій, констант і фабричних методів, які не залежать від конкретного об'єкта. ## Теорія ### TL;DR - Звичайні поля й методи належать екземплярам, статичні, самому класу. - Доступ до статики: `ClassName.member`. Через екземпляр вона недоступна (`u.role` дасть `undefined`). - Усередині `static` метода `this`, це сам клас, тож статика може читати й змінювати іншу статику. - Статичні члени успадковуються при `extends`. - Вбудовані приклади: `Math.random()`, `Date.now()`, `Object.keys()`, `Array.isArray()`. - ES2022 дозволяє приватну статику: `static #field`. ### Швидкий приклад ```javascript class User { static role = 'Користувач'; static createGuest() { return new User('Гість'); } constructor(name) { this.name = name; } } console.log(User.role); // 'Користувач' console.log(User.createGuest()); // User { name: 'Гість' } const u = new User('Maria'); console.log(u.role); // undefined, екземпляр не бачить статику ``` ### Що таке статична властивість або метод Зазвичай методи й властивості класу належать **екземплярам**, тобто об'єктам, створеним через `new`: ```javascript class User { constructor(name) { this.name = name; // належить екземпляру } sayHi() { // теж належить екземпляру console.log(`Привіт, ${this.name}`); } } const u = new User('Maria'); u.sayHi(); // Привіт, Maria ``` Щойно додаємо `static`, член переїжджає на сам клас. Статика доступна тільки через клас (`User`), а не через його об'єкти (`u`). ### Навіщо це потрібно і вбудовані приклади Статичні властивості й методи використовують, коли дані або функції: - **не залежать від конкретного екземпляра**, - **спільні для всього класу**. Приклади: - фабричні методи (`User.createGuest()`), - глобальні константи (`Math.PI`), - службові утиліти (`Date.now()`). Сам JavaScript активно використовує `static` у стандартних класах: | Клас | Статичний метод | | --- | --- | | `Math` | `Math.random()`, `Math.max()` | | `Date` | `Date.now()` | | `Object` | `Object.keys()`, `Object.assign()` | | `Array` | `Array.isArray()` | > Наприклад, ви не створюєте екземпляр `Math`, а просто викликаєте `Math.max(1, 5, 9)`. Це і є статичний метод. ### Успадкування статики та this всередині static Якщо клас наслідує інший через `extends`, то **статичні члени теж успадковуються**: ```javascript class Animal { static category = 'Тварини'; static info() { console.log('Це тварина'); } } class Dog extends Animal {} console.log(Dog.category); // 'Тварини' Dog.info(); // 'Це тварина' ``` Тобто `Dog` успадкував статику від `Animal`. Усередині статичного методу можна звертатися до інших статичних властивостей через `this`: ```javascript class Counter { static count = 0; static increment() { this.count++; } static reset() { this.count = 0; } } Counter.increment(); Counter.increment(); console.log(Counter.count); // 2 Counter.reset(); console.log(Counter.count); // 0 ``` > Тут `this` усередині `static`, це **сам клас**, а не екземпляр. ### Приватні статичні поля ES2022 дозволяє оголошувати **приватні статичні** властивості через `#`: ```javascript class Config { static #secret = '12345'; static getSecret() { return this.#secret; } } console.log(Config.getSecret()); // '12345' console.log(Config.#secret); // SyntaxError ``` > Такі поля видно тільки всередині самого класу, навіть нащадки їх не бачать. ### Порівняння зі звичайними властивостями | Характеристика | Звичайна властивість | Статична властивість | | --- | --- | --- | | Де зберігається | У кожному екземплярі (`this`) | У самому класі (`ClassName`) | | Доступ через екземпляр | Так | Ні | | Доступ через клас | Ні | Так | | Успадковується при `extends` | Так | Так | | Контекст `this` у методі | Екземпляр | Клас | Реальний приклад, фабричний метод (factory pattern): ```javascript class User { constructor(name, role) { this.name = name; this.role = role; } static createAdmin(name) { return new User(name, 'admin'); } static createGuest() { return new User('Гість', 'guest'); } } const admin = User.createAdmin('Maria'); const guest = User.createGuest(); console.log(admin); // { name: 'Maria', role: 'admin' } console.log(guest); // { name: 'Гість', role: 'guest' } ``` Зручно, коли треба створювати об'єкти за певними шаблонами. Підсумкова таблиця: | Що робить `static` | Пояснення | | --- | --- | | Прив'язує властивість або метод до класу, а не до об'єктів | Доступ через `ClassName`, не через `this` екземпляра | | Часто використовується для утиліт, констант, фабрик | Наприклад, `Math.random()` | | Успадковується при `extends` | Нащадки отримують статику батька | | Усередині `static` `this` вказує на сам клас | Можна звертатися до інших статичних властивостей | | Можна зробити приватним (`static #field`) | Видно тільки всередині класу | ### Типові помилки - **Звертатися до статики через екземпляр.** `u.role` дасть `undefined`, бо статика живе на класі, а не в ланцюжку прототипів екземпляра. - **Плутати `this` у статичному й звичайному методі.** У статичному `this`, це клас, у звичайному, екземпляр. - **Передавати статичний метод як колбек.** `setTimeout(Counter.increment, 0)` втратить `this`, треба `Counter.increment.bind(Counter)` або стрілкову обгортку. - **Тримати в статиці стан, який має бути в екземплярі.** Статичне поле одне на весь клас, тому воно перетворюється на глобальну змінну з усіма її проблемами. - **Вважати, що приватна статика доступна нащадкам.** `static #field` видно лише всередині класу, де його оголошено.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.