Skip to main content

Can private properties be inherited?

1. Example: A Private Field on the Parent Is Not Accessible in the Subclass

javascript
class Parent { #secret = "parent secret"; showSecret() { console.log(this.#secret); } } class Child extends Parent { reveal() { console.log(this.#secret); // Error } } const c = new Child(); c.showSecret(); // "parent secret" c.reveal(); // SyntaxError: Private field '#secret' must be declared in an enclosing class

Explanation:

  • The private field #secret "belongs" only to the Parent class.
  • The Child class doesn't even know it exists.
  • So accessing this.#secret inside Child is impossible.

2. How This Works Under the Hood

When you declare #field, JavaScript creates a unique hidden identifier, accessible only inside that class's body.

So even if you use the same name #secret in two classes, these are two different fields, with no connection between them:

javascript
class Parent { #secret = "parent"; getParentSecret() { return this.#secret; } } class Child extends Parent { #secret = "child"; getChildSecret() { return this.#secret; } } const c = new Child(); console.log(c.getParentSecret()); // parent console.log(c.getChildSecret()); // child

Here, #secret on Parent and #secret on Child are two independent properties, with the same name but different "hidden keys".


3. Why Private Fields Can't Be Inherited

This is a deliberate decision by the language's authors:

  • To preserve strict encapsulation (everything starting with # is fully hidden).
  • To avoid name conflicts between private properties of different classes.
  • To simplify optimization in engines (V8, SpiderMonkey, etc.).

That's why extends inherits methods, but doesn't grant access to the parent's private fields.


4. So How Do You Share Private Data Between a Parent and a Subclass

If you want private data to be accessible in subclasses, use one of the following techniques:


Option 1: Use a Protected-Like Convention (_field)

This isn't real privacy, but it's often used in practice:

javascript
class Parent { _secret = "accessible to subclasses"; showSecret() { console.log(this._secret); } } class Child extends Parent { reveal() { console.log(this._secret); // Works } }

Here, _secret is just a convention meaning "don't touch this property from outside". It's not protected, but it's accessible to subclasses.


Option 2: Use Getters / Setters

The parent can control access through methods, and the subclass can use those methods without knowing the implementation details.

javascript
class Parent { #secret = "parent secret"; getSecret() { return this.#secret; } } class Child extends Parent { reveal() { console.log(this.getSecret()); // can be retrieved through the method } } new Child().reveal(); // parent secret

This way, privacy is preserved, but access is still possible through an interface.


Option 3: Use a WeakMap (an Alternative to # Before ES2022)

This is an older but flexible way to have "private" data with controlled access.

javascript
const privates = new WeakMap(); class Parent { constructor() { privates.set(this, { secret: "shared secret" }); } get _data() { return privates.get(this); } } class Child extends Parent { reveal() { console.log(this._data.secret); // accessible } } new Child().reveal(); // shared secret

A WeakMap lets you hide data while still making it accessible in subclasses.


5. Summary: Comparing the Approaches

ApproachPrivacyAccessible to SubclassesReal Protection
#fieldFullNoAbsolute
_field (by convention)PartialYesNo protection
WeakMapAlmost fullYesYes
Getter/setterThrough an interfaceYesControlled

Brief Conclusion

Private fields (#field) are not inherited. Each class has its own private space. Subclasses cannot access the parent's private fields directly. If you need to share private data, use:

  • _field (a convention),
  • getters/setters,
  • or a WeakMap with access for subclasses.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.