Consider the following code:
class MyBase {
constructor(b) {
this.myOverrideMethod(b);
}
myOverrideMethod(b) {}
}
class MyClass extends MyBase {
constructor(b) {
super(b);
}
myOverrideMethod(b) {
if (b) {
this.mySpecificMethod();
} else {
this.#myPrivateMethod();
}
}
mySpecificMethod() {
console.log('mySpecificMethod');
}
#myPrivateMethod = () => {
console.log('#myPrivateMethod');
};
}
new MyClass(true); // <-- "mySpecificMethod"
new MyClass(false); // <-- Uncaught TypeError: Cannot read private member #myPrivateMethod
// from an object whose class did not declare it
Consider the following code:
class MyBase {
constructor(b) {
this.myOverrideMethod(b);
}
myOverrideMethod(b) {}
}
class MyClass extends MyBase {
constructor(b) {
super(b);
}
myOverrideMethod(b) {
if (b) {
this.mySpecificMethod();
} else {
this.#myPrivateMethod();
}
}
mySpecificMethod() {
console.log('mySpecificMethod');
}
#myPrivateMethod = () => {
console.log('#myPrivateMethod');
};
}
new MyClass(true); // <-- "mySpecificMethod"
new MyClass(false); // <-- Uncaught TypeError: Cannot read private member #myPrivateMethod
// from an object whose class did not declare it
The overridden method of myOverrideMethod()
is called in the constructor of the "base" class. Since this
points to an instance of MyClass
, the overrided method in the derived class is invoked correctly. The regular method of mySpecificMethod()
gets called successfully, while invoking the private field of #myPrivateMethod()
throws the following "TypeError":
Uncaught TypeError: Cannot read private member
#myPrivateMethod
from an object whose class did not declare it
The error message does not convey the issue as being a private field access violation, but rather evokes the this
does not yet reference an instance of MyClass
but still references an instance of MyBase
! However, why is that and how to successfully invoke the private method of #myPrivateMethod()
?
- Never call overrideable methods from the constructor, and don't use class fields for methods. – Bergi Commented Apr 15, 2020 at 20:20
1 Answer
Reset to default 5This is only an issue when trying to call the private method during the constructor. I think it's because the child class hasn't yet been fully constructed while in the parent's constructor, so the private method isn't available yet.
See the example below where I call this.myOverrideMethod()
from an ordinary method, and the call is allowed.
class MyBase {
constructor() {
}
doit(b) {
this.myOverrideMethod(b);
}
myOverrideMethod(b) {}
}
class MyClass extends MyBase {
constructor() {
super();
}
myOverrideMethod(b) {
if (b) {
this.mySpecificMethod();
} else {
this.#myPrivateMethod();
}
}
mySpecificMethod() {
console.log('mySpecificMethod');
}
#myPrivateMethod = () => {
console.log('#myPrivateMethod');
};
}
new MyClass().doit(true);
new MyClass().doit(false);