Suggest an editImprove this articleRefine the answer for “Private class properties”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A private property is a class field prefixed with `#`, reachable only inside the body of the class that declares it; from outside, touching it is a syntax error rather than `undefined`.** Private methods and private statics work the same way. Private fields are not inherited, never show up in `for...in` or `Object.keys`, and their names cannot be built dynamically. ```javascript class User { #password = '12345'; checkPassword(pwd) { return pwd === this.#password; } } new User().checkPassword('12345'); // true ``` **Key point:** `#` is real, language level privacy, not a convention like `_password` that anyone can bypass.Shown above the full answer for quick recall.Answer (EN)Image**A private property is a class property whose name starts with `#`: it is reachable only inside the class itself and is completely unavailable, even invisible, from the outside.** Unlike the old underscore convention, this is a language level guarantee rather than an agreement between developers. ## Theory ### TL;DR - Syntax: `#field` in the class body, accessed as `this.#field`. - From outside, `obj.#field` is a `SyntaxError`, not `undefined`. - Fields, methods and static members can all be private (`static #token`). - Private fields are not inherited: a subclass cannot see the parent's private fields. - They do not appear in `for...in`, `Object.keys` or `JSON.stringify`. - A private field name cannot be computed dynamically, it is always written literally in the code. ### Quick example ```javascript class User { #password = '12345'; // a private property checkPassword(pwd) { return pwd === this.#password; } } const u = new User(); console.log(u.#password); // SyntaxError, no direct access console.log(u.password); // undefined console.log(u.checkPassword('12345')); // true ``` Here: - `#password` is a private property, - it is reachable only inside the class's own methods, - from outside, an access attempt raises a **syntax error**, not merely `undefined`. ### Private fields and methods You can hide methods as well as properties: ```javascript 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, it is a private method console.log(acc.getBalance()); // 100 ``` Private methods are handy for helper logic that the class's users should never see. How this differs from regular properties: | Property | Visibility | Changeable from outside? | Enumerable in `for...in`? | | --- | --- | --- | --- | | `this.value` | Public | Yes | Yes | | `#value` | Private | No | No | ### Why the underscore convention is not enough Before `#` existed, developers **imitated privacy** by convention, prefixing the name with `_`: ```javascript class User { _password = '12345'; } ``` But that **protects nothing**: ```javascript const u = new User(); u._password = 'hacked'; // changed without any resistance ``` `#` is **real protection at the language level**, not just a team agreement. ### Inheritance and private statics Private fields are **not inherited** and are **not available in subclasses**: ```javascript class Parent { #secret = 'parent secret'; reveal() { console.log(this.#secret); } } class Child extends Parent { test() { console.log(this.#secret); // Error, it is the parent's private field } } ``` > Every class sees **only its own private fields**, even when it extends another one. Static members can be private too: ```javascript class Config { static #token = 'abc123'; static getToken() { return this.#token; } } console.log(Config.getToken()); // 'abc123' console.log(Config.#token); // Error ``` This is useful when class level confidential data must stay hidden. ### A real world example and the limits The private `#balance` field protects the data from direct tampering: ```javascript class BankAccount { #balance = 0; deposit(amount) { if (amount <= 0) throw new Error('The 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, it cannot be changed from outside ``` One important limitation: a private property **cannot be created dynamically**. Private field names are fixed in the source: ```javascript const name = '#secret'; class A { [name] = 123; // Error, a variable cannot be used here } ``` This is deliberate, it keeps the guarantee airtight: the field is reachable only through a literal `#` name. Summary table: | Feature | Private property (`#field`) | | --- | --- | | Visibility | Only inside the class | | Declaration | With `#name` | | Access from outside | An error, not just `undefined` | | Inheritance | Not passed to subclasses | | Allowed on statics | Yes (`static #secret`) | | Works with getters and setters | Yes | | Can be created dynamically | No | ### Common mistakes - **Confusing `#field` with `_field`.** The underscore is only a convention, any code can overwrite such a field. - **Expecting `undefined` from outside.** Touching `obj.#field` outside the class fails at parse time, so it breaks the whole file, not just that line. - **Counting on subclass access.** A parent's private fields are invisible in a subclass; if you need access, use a protected style pattern with a regular field or a getter. - **Using `in` carelessly for feature detection.** The `#field in obj` check does work, but only inside the class that declares the field. - **Forgetting that private fields are not serialized.** `JSON.stringify(acc)` will not show `#balance`, so persisting the state needs an explicit method.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.