In this program:
class Example {
#privateMember = 123;
// these are fine
addNumber (n) { return this.#privateMember + n; }
doAddNumber (n) { return this.addNumber(n); }
// "cannot read private member #privateMember from an
// object whose class did not declare it"
#operations = { add: this.addNumber };
operate (n) { return this.#operations.add(n); }
}
const ex = new Example();
console.log(ex.addNumber(77));
console.log(ex.doAddNumber(77));
console.log(ex.operate(77));
Calling addNumber
works fine, so does doAddNumber
, but calling operate
yields the error:
TypeError: Cannot read private member #privateMember from an object whose class did not declare it
at Object.addNumber [as add] (<anonymous>:11:17)
at Example.operate (<anonymous>:20:29)
at <anonymous>:27:16
at dn (<anonymous>:16:5449)
I can't make any sense of this error because:
addNumber
works fine, so its not a syntax error or a typo at least.doAddNumber
works fine, so its not a problem calling functions from other functions.operate
just calls addNumber
which, from (1), works fine.this
is an object whose class declares #privateMember
... I mean, this
is an Example
and I can see that it's declared in Example
. It's right there... I typed it myself...I found TypeError: Cannot read private member from an object whose class did not declare it but I can't understand how it applies, if it applies.
I can't figure out what's going on here. Why doesn't operate
work even though addNumber
and doAddNumber
do?
In my real code (this is just a minimal example), I am trying to use a dictionary like #operations
to hold implementations of a number of various algorithms for performing a task, indexed by a string ID, where the string algorithm ID is specified to the constructor. This is also convenient because I can get the keys from this dictionary to provide a list of valid algorithm IDs without having to duplicate that list anywhere. Now, I can just switch it to an if
statement and make sure I keep the queryable list up to date as well, but I can't understand why this doesn't work.
When you set #operations.addNumber
and then call it, this === #operations
, not ex
, which fails because ex.#operarions.#privateMember
does not exist.
If I change your Example
class with
#operations = { add: this.addNumber.bind(this)};
then ex.#operations.add
runs with this === ex
and your code returns
> 200
> 200
> 200