- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Private Fields
JavaScript Classes
JavaScript Private Fields
A field starting with a hash is private and cannot be read from outside the class.
The underscore convention was only ever a hint; nothing enforced it.
A # field is genuinely inaccessible from outside.
Example
Example
javascript
class Account {
#balance = 100;
getBalance() {
return this.#balance;
}
}
console.log(new Account().getBalance());The balance is readable through the method but not directly.
What is a Private Field?
A name beginning with # is private to the class body.
Reading it from outside is a syntax error, not just a bad idea.
Methods can be private too.
Syntax
Syntax
javascript
class Name {
#secret = value;
#privateMethod() {}
}The # is part of the name, not an operator.
It Really Is Private
Unlike the underscore convention, this cannot be worked around.
It does not appear in Object.keys either.
Example
Example
javascript
class Account {
#balance = 100;
name = "current";
}
const account = new Account();
console.log(Object.keys(account).join(","));Only the public field is listed.
Controlled Access
Expose exactly what you want, and nothing more.
Example
Example
javascript
class Account {
#balance = 0;
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
}
return this.#balance;
}
}
const account = new Account();
account.deposit(-50);
console.log(account.deposit(100));The negative deposit was refused and the balance stayed safe.
Private Methods
Helpers that are nobody else's business can be hidden too.
Example
Example
javascript
class Order {
#price = 100;
#tax() {
return this.#price * 0.2;
}
total() {
return this.#price + this.#tax();
}
}
console.log(new Order().total());The output is 120, and #tax cannot be called from outside.
The Old Underscore Convention
An underscore says please do not touch this, but nothing stops you.
You will still see it constantly in older code.
Example
Example
javascript
class Account {
constructor() {
this._balance = 100;
}
}
const account = new Account();
account._balance = 999999;
console.log(account._balance);Nothing prevented the change, which is exactly the problem.
Private Fields Are Not Inherited
A child class cannot reach its parent's private fields.
That is the point: private means private to that class body.
Example
Example
javascript
class Parent {
#secret = "hidden";
reveal() {
return this.#secret;
}
}
class Child extends Parent {}
console.log(new Child().reveal());The child can use the public method but not the field itself.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Private Fields</title>
</head>
<body>
<h1>Private Fields</h1>
<p id="out"></p>
<script>
class Account {
#balance = 0;
constructor(owner) {
this.owner = owner;
}
deposit(amount) {
if (amount <= 0) return this.#balance;
this.#balance += amount;
return this.#balance;
}
get balance() {
return this.#balance;
}
}
const account = new Account("Ada");
account.deposit(100);
account.deposit(-500);
document.getElementById("out").textContent =
account.owner + " has " + account.balance;
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try reaching in:
Add account.#balance = 999 and see the syntax error.
Important Points
- A
#name is private to the class body. - It cannot be read or written from outside.
- Private fields do not appear in
Object.keys. - Methods can be private too.
- A child class cannot access a parent's private fields.
Conclusion
Private fields turn encapsulation from a convention into a rule.
Exposing a method or a getter gives you control over how data is reached.
This is the modern replacement for the underscore prefix.
