~/
hackweb.dev
JavaScript Private & Public Fields
Quiz
⌘K
...
~/
/tutorials
/js/js-private-public-fields/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/js/24js-private-public-fields
Write
Preview
Diff
# JavaScript Private & Public Fields Control access to object properties with true encapsulation using `#`. ## Public Fields Declared directly in the class body — accessible from outside: ```javascript class User { name; email; constructor(name, email) { this.name = name; this.email = email; } } let user = new User("John", "john@example.com"); console.log(user.name); // "John" ``` ## Private Fields Prefix with `#` — completely inaccessible outside the class: ```javascript class BankAccount { #balance; #pin; constructor(owner, initialBalance, pin) { this.owner = owner; this.#balance = initialBalance; this.#pin = pin; } getBalance(pin) { if (pin !== this.#pin) throw new Error("Invalid PIN"); return this.#balance; } deposit(amount, pin) { if (pin !== this.#pin) throw new Error("Invalid PIN"); this.#balance += amount; return this; } } let account = new BankAccount("John", 1000, "1234"); console.log(account.getBalance("1234")); // 1000 // console.log(account.#balance); // Syntax Error! ``` **Remember:** `#` fields throw a `SyntaxError` if accessed from outside the class. ## Private Methods Internal helpers hidden from the outside: ```javascript class PasswordValidator { #password; constructor(pw) { this.#password = pw; } #hasMinLength(p) { return p.length >= 8; } #hasUppercase(p) { return /[A-Z]/.test(p); } #hasNumber(p) { return /[0-9]/.test(p); } validate() { let errors = []; if (!this.#hasMinLength(this.#password)) errors.push("Min 8 characters"); if (!this.#hasUppercase(this.#password)) errors.push("Need uppercase"); if (!this.#hasNumber(this.#password)) errors.push("Need a number"); return { valid: errors.length === 0, errors }; } } let v = new PasswordValidator("Secret123!"); console.log(v.validate()); // { valid: true, errors: [] } ``` ## Public vs Private — When to Use Which ```javascript class Product { #name; // Private: needs validation #price; // Private: must be non-negative category; // Public: safe to access directly constructor(name, price, category) { this.name = name; this.price = price; this.category = category; } get name() { return this.#name; } set name(v) { if (!v || v.length < 2) throw new Error("Name too short"); this.#name = v; } get price() { return this.#price; } set price(v) { if (v < 0) throw new Error("Negative price"); this.#price = v; } } ``` **Rule of thumb:** Private if it needs validation. Public if safe to access directly. ## Complete Example: Cache ```javascript class Cache { #cache = new Map(); #maxSize; #ttl; constructor(maxSize = 100, ttl = 60000) { this.#maxSize = maxSize; this.#ttl = ttl; } #isExpired(e) { return Date.now() - e.timestamp > this.#ttl; } #evict() { if (this.#cache.size >= this.#maxSize) { this.#cache.delete(this.#cache.keys().next().value); } } set(key, value) { this.#evict(); this.#cache.set(key, { value, timestamp: Date.now() }); return this; } get(key) { let e = this.#cache.get(key); if (!e || this.#isExpired(e)) { this.#cache.delete(key); return null; } return e.value; } has(key) { return this.get(key) !== null; } get size() { return this.#cache.size; } } let cache = new Cache(3, 5000); cache.set("a", 1).set("b", 2).set("c", 3); cache.set("d", 4); // Evicts "a" console.log(cache.get("a")); // null ``` ## Best Practices - **Use private for sensitive data** — Balances, passwords, keys - **Use public for the API surface** — Safe to access directly - **Provide public methods for controlled access** — Validate before modifying - **Don't over-encapsulate** — Not every field needs to be private ## Common Mistakes - **Forgetting `#`** — Private fields require the hash prefix - **Over-encapsulating** — Too many privates clutter the API - **Not providing access** — Private data with no way to use it is useless - **Returning mutable objects from getters** — Breaks encapsulation
No changes yet
Reset to original
Submit suggestion
cancel