Private properties
1. What a Private Property Is
A private property is a class property that starts with the # symbol.
It is accessible only inside the class itself,
and is completely inaccessible from outside (and not even visible).
class User {
#password = "12345"; // private property
checkPassword(pwd) {
return pwd === this.#password;
}
}
const u = new User();
console.log(u.#password); // SyntaxError: you cannot access it directly
console.log(u.password); // undefined
console.log(u.checkPassword("12345")); // trueHere:
#passwordis a private property- it's accessible only inside the class's methods
- from outside, attempting to access it causes a syntax error, not just
undefined.
2. Private Methods
You can hide not only properties, but methods too:
class Account {
#balance = 0;
#log(message) {
console.log("[LOG]:", message);
}
deposit(amount) {
this.#balance += amount;
this.#log(`Balance topped up by ${amount}`);
}
getBalance() {
return this.#balance;
}
}
const acc = new Account();
acc.deposit(100);
// acc.#log("test"); // Error: private method
console.log(acc.getBalance()); // 100Private methods are often used for "helper logic" that doesn't need to be exposed to the caller.
3. Difference From Regular Properties
| Property | Visibility | Can It Be Changed From Outside? | Can It Be Enumerated (for...in)? |
|---|---|---|---|
this.value | Public | Yes | Yes |
#value | Private | No | No |
4. Why a Plain "_" Isn't Enough
Before # existed, developers simulated privacy
through convention, putting _ before the name:
class User {
_password = "12345";
}But this doesn't protect anything:
const u = new User();
u._password = "hacked"; // Can be changed# is real, language-level protection,
not just a convention.
5. Private Fields and Inheritance
Private fields are not inherited and are not accessible in subclasses:
class Parent {
#secret = "parent secret";
reveal() {
console.log(this.#secret);
}
}
class Child extends Parent {
test() {
console.log(this.#secret); // Error: the parent's private field
}
}Each class sees only its own private fields, even if it inherits from another one.
6. You Can Use Private Static Fields
class Config {
static #token = "abc123";
static getToken() {
return this.#token;
}
}
console.log(Config.getToken()); // "abc123"
console.log(Config.#token); // ErrorThis is useful when you want to hide class-level confidential data.
7. A Real-World Usage Example
class BankAccount {
#balance = 0;
deposit(amount) {
if (amount <= 0) throw new Error("Amount must be positive");
this.#balance += amount;
}
withdraw(amount) {
if (amount > this.#balance) throw new Error("Insufficient funds");
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; Error: cannot be changed from outsideThe private field #balance protects the data from direct interference.
8. You Cannot Create a Private Property Dynamically
Private property names are hardcoded in the source. You cannot create them dynamically:
const name = "#secret";
class A {
[name] = 123; // Error: you cannot use a variable
}This is done for full security: access is only possible via the literal
#symbol.
Summary
| Feature | Private Property (#field) |
|---|---|
| Visibility | Only inside the class |
| Declared | Via #name |
| Access from outside | Error (not just undefined) |
| Inheritance | Not passed on to subclasses |
| Usable in static members | Yes (static #secret) |
| Can be combined with getters/setters | Yes |
| Can be created dynamically | No |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.