Префікс # робить поле, метод чи аксесор класу справді приватним: доступ до нього можливий лише з коду всередині тіла класу.
class Cart {
#items = [];
static #instances = 0;
constructor() {
Cart.#instances++;
}
add(product, qty = 1) {
this.#validate(qty);
this.#items.push({ product, qty });
}
get total() {
return this.#items.reduce((sum, { product, qty }) => sum + product.price * qty, 0);
}
#validate(qty) {
if (qty <= 0) throw new RangeError('Кількість має бути додатною');
}
}
const cart = new Cart();
cart.add({ price: 100 }, 2);
cart.total; // 200
cart.#items; // SyntaxError - навіть не помилка під час виконання, а помилка розбору
Чим відрізняється від конвенції _items:
_items- лише домовленість: властивість доступна, видна вObject.keys, уJSON.stringify, її можна змінити ззовні;#items- приватність гарантована мовою: не видно вObject.keys, не серіалізується в JSON, не доступна черезobj['#items'], проксі й рефлексію.
Корисні можливості:
- перевірка «бренду» - чи об'єкт створено цим класом, без
instanceof(якого можна обдурити підміною прототипу):
class Money {
#amount;
static isMoney(value) {
return #amount in value;
}
}
- статичні приватні поля й методи (
static #instances); - статичні блоки ініціалізації (
static { ... }) - мають доступ до приватних елементів класу.
Обмеження й підводні камені:
- приватні поля не наслідуються в доступі: підклас не бачить
#itemsбатьківського класу. Для «захищених» (якprotectedу PHP) окремого синтаксису немає; Proxyнад об'єктом з приватними полями ламає методи: метод, викликаний через проксі, отримуєthis= проксі, а в проксі немає приватних полів -TypeError. Це помітно в реактивних системах: Vue робить об'єкти реактивними черезProxy, тож класи з#полями вreactive()можуть падати. Для таких класів -markRawчиshallowRef;- приватні поля оголошуються в тілі класу - додати їх динамічно неможливо;
structuredCloneіJSON.stringifyїх не копіюють.
TypeScript має і модифікатор private, і #. private - лише перевірка компілятора, після компіляції поле звичайне; # - справжня приватність під час виконання.