Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Приватні властивості класу». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Приватна властивість, це поле класу з префіксом `#`, доступне лише всередині тіла того класу, де його оголошено; ззовні звернення до нього, це не `undefined`, а синтаксична помилка.** Так само можна оголошувати приватні методи й приватну статику. Приватні поля не успадковуються, не потрапляють у `for...in` і `Object.keys`, а їхні імена не можна створити динамічно. ```javascript class User { #password = '12345'; checkPassword(pwd) { return pwd === this.#password; } } new User().checkPassword('12345'); // true ``` **Ключове:** `#`, це справжня приватність на рівні мови, а не угода на кшталт `_password`, яку легко обійти.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Приватна властивість, це властивість класу, ім'я якої починається з `#`: вона доступна тільки всередині самого класу, а ззовні повністю недоступна і навіть не видима.** На відміну від старої угоди з підкресленням, це гарантія рівня мови, а не домовленість між розробниками. ## Теорія ### TL;DR - Синтаксис: `#field` у тілі класу, доступ через `this.#field`. - Ззовні `obj.#field`, це `SyntaxError`, а не `undefined`. - Приватними бувають і поля, і методи, і статичні члени (`static #token`). - Приватні поля не успадковуються: нащадок не бачить приватних полів батька. - Вони не перелічуються у `for...in`, `Object.keys` і не потрапляють у `JSON.stringify`. - Ім'я приватного поля не можна обчислити динамічно, воно завжди жорстко записане в коді. ### Швидкий приклад ```javascript class User { #password = '12345'; // приватна властивість checkPassword(pwd) { return pwd === this.#password; } } const u = new User(); console.log(u.#password); // SyntaxError, напряму звернутися не можна console.log(u.password); // undefined console.log(u.checkPassword('12345')); // true ``` Тут: - `#password`, це приватна властивість, - вона доступна тільки всередині методів класу, - ззовні спроба звернення дає **синтаксичну помилку**, а не просто `undefined`. ### Приватні поля й методи Ховати можна не лише властивості, а й методи: ```javascript class Account { #balance = 0; #log(message) { console.log('[LOG]:', message); } deposit(amount) { this.#balance += amount; this.#log(`Баланс поповнено на ${amount}`); } getBalance() { return this.#balance; } } const acc = new Account(); acc.deposit(100); // acc.#log('test'); // Помилка, це приватний метод console.log(acc.getBalance()); // 100 ``` Приватні методи зручні для допоміжної логіки, яку не треба показувати користувачеві класу. Відмінність від звичайних властивостей: | Властивість | Видимість | Можна змінити ззовні? | Перелічується у `for...in`? | | --- | --- | --- | --- | | `this.value` | Публічна | Так | Так | | `#value` | Приватна | Ні | Ні | ### Чому угода з підкресленням не підходить До появи `#` розробники **імітували приватність** угодою: ставили `_` перед іменем. ```javascript class User { _password = '12345'; } ``` Але це **нічого не захищає**: ```javascript const u = new User(); u._password = 'hacked'; // спокійно змінюється ``` `#`, це **справжній захист на рівні мови**, а не просто домовленість між людьми в команді. ### Успадкування та приватна статика Приватні поля **не успадковуються** і **недоступні в підкласах**: ```javascript class Parent { #secret = 'parent secret'; reveal() { console.log(this.#secret); } } class Child extends Parent { test() { console.log(this.#secret); // Помилка, це приватне поле батька } } ``` > Кожен клас бачить **тільки свої приватні поля**, навіть якщо наслідує інший. Статичні члени теж можуть бути приватними: ```javascript class Config { static #token = 'abc123'; static getToken() { return this.#token; } } console.log(Config.getToken()); // 'abc123' console.log(Config.#token); // Помилка ``` Це корисно, коли треба сховати конфіденційні дані рівня класу. ### Реальний приклад і обмеження Приватне поле `#balance` захищає дані від прямого втручання: ```javascript class BankAccount { #balance = 0; deposit(amount) { if (amount <= 0) throw new Error('Сума має бути додатною'); this.#balance += amount; } withdraw(amount) { if (amount > this.#balance) throw new Error('Недостатньо коштів'); this.#balance -= amount; } getBalance() { return this.#balance; } } const acc = new BankAccount(); acc.deposit(500); console.log(acc.getBalance()); // 500 acc.withdraw(200); console.log(acc.getBalance()); // 300 // acc.#balance = 100000; // Помилка, ззовні змінити не можна ``` Важливе обмеження: приватну властивість **не можна створити динамічно**. Імена приватних полів жорстко задані в коді: ```javascript const name = '#secret'; class A { [name] = 123; // Помилка, змінну тут використати не можна } ``` Так зроблено заради повної гарантії доступу: дістатися до поля можна лише через літерал з `#`. Підсумкова таблиця: | Особливість | Приватна властивість (`#field`) | | --- | --- | | Видимість | Тільки всередині класу | | Оголошення | Через `#ім'я` | | Доступ ззовні | Помилка, а не просто `undefined` | | Успадкування | Не передається нащадкам | | Можна в статиці | Так (`static #secret`) | | Поєднується з геттерами та сетерами | Так | | Створити динамічно | Ні | ### Типові помилки - **Плутати `#field` і `_field`.** Підкреслення, це лише угода, будь-який код може перезаписати таке поле. - **Очікувати `undefined` ззовні.** Звернення до `obj.#field` поза класом, це помилка ще на етапі парсингу, тому вона ламає весь файл, а не лише цей рядок. - **Розраховувати на доступ із нащадка.** Приватні поля батька не видно в підкласі; якщо потрібен доступ, використовуйте `protected`-подібний патерн через звичайне поле або геттер. - **Перевіряти наявність поля через `in` на чужому об'єкті без обережності.** Для приватних полів працює `#field in obj`, але тільки всередині класу, який їх оголошує. - **Забувати, що приватні поля не серіалізуються.** `JSON.stringify(acc)` не покаже `#balance`, тому для збереження стану потрібен явний метод.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.