What are private class fields and methods (#)?
Prefixing a class field or method with # makes it truly private — accessible only inside that class.
Real privacy — unlike the old underscore convention, # is enforced by the language; outside access throws an error.
Fields and methods — both can be private.
Benefit: hide internal state and helpers, exposing only a clean public interface.
class BankAccount {
#balance = 0; // Private field
#pin; // Private field
constructor(owner, pin, initialBalance) {
this.owner = owner; // Public
this.#pin = pin; // Private
this.#balance = initialBalance;
}
// Private method
#validatePin(pin) {
return this.#pin === pin;
}
deposit(amount) {
if (amount <= 0) throw new Error('Invalid amount');
this.#balance += amount;
return this.#balance;
}
withdraw(amount, pin) {
if (!this.#validatePin(pin)) throw new Error('Invalid PIN');
if (amount > this.#balance) throw new Error('Insufficient funds');
this.#balance -= amount;
return this.#balance;
}
get balance() { return this.#balance; } // Controlled access
}
const account = new BankAccount('John', 1234, 1000);
account.deposit(500); // OK
account.withdraw(200, 1234); // OK
console.log(account.balance); // 1300 (via getter)
// console.log(account.#balance); // SyntaxError!
// account.#validatePin(1234); // SyntaxError!#balance and #pin are truly private — SyntaxError if accessed outside the class. #validatePin is a private method. The getter (get balance) provides controlled read-only access.
Unlike _convention, # is enforced by the language. Subclasses cannot access parent's private fields either.