Iron-Clad Encapsulation

Private fields (starting with #) are not just a naming convention — they are physically enforced by the JavaScript engine.

How # Fields Differ From _ Convention

Feature_field (convention)#field (private)
Actually private?No — just a warning signYes — enforced by engine
Accessible via string?Yes: obj['_field']No — obj['#field'] returns undefined
Visible in for..in?YesNo
Error timingRuntime (if accessed wrong)Compile-time (SyntaxError)
class User {
  #password = '12345';

  checkPassword(input) {
    return this.#password === input;
  }
}

const user = new User();
console.log(user.checkPassword('12345')); // true
console.log(user.#password); // SyntaxError — blocked at parse time!
Important

Private fields are NOT inherited. Even a child class cannot read a #field from its parent. If child classes need access, use the _underscore convention or provide getter/setter methods in the parent class.

Tip

Use private fields for truly sensitive data (passwords, tokens, internal counters) or complex internal state that external code should never be able to corrupt.