When defining a private member using #
, and then re-defining some member that uses this private member, you will find that you cannot use it anymore:
class Foo {
#secret = "Keyboard Cat";
method() {
console.log(this.#secret);
}
}
const target = Foo.prototype;
const key = "method";
const desc = Object.getOwnPropertyDescriptor(target, key);
const og = desc.value;
desc.value = function (...args) {
return og.apply(target, args);
};
Object.defineProperty(target, key, desc);
new Foo().method();
Uncaught TypeError: Cannot read private member #secret from an object whose class did not declare it
Why? All I have done is wrap around the original method in this case. Note that this example is a dramatic simplification of using decorators with TypeScript. How could I get around this while still being able to redefine and "change" the method?
Here's the same thing, but with a TypeScript decorator:
const Curse: MethodDecorator = (target, _, desc) => {
const og = desc.value as Function;
desc.value = function (...args: any[]) {
return og.apply(target, args);
} as any;
return desc;
};
class Foo {
#secret = "Keyboard Cat";
@Curse
method() {
console.log(this.#secret);
}
}
new Foo().method();
CodePudding user response:
The mistake you made is to apply the method to the target
, which is Foo.prototype
, not to the new Foo
instance via the this
keyword:
class Foo {
#secret = "Keyboard Cat";
method() {
console.log(this.#secret);
}
}
const target = Foo.prototype;
const key = "method";
const desc = Object.getOwnPropertyDescriptor(target, key);
const orig = desc.value;
desc.value = function (...args) {
return orig.apply(this, args);
// ^^^^
};
Object.defineProperty(target, key, desc);
new Foo().method();
Foo.prototype
does not have the #secret
private field. You'll get the same error with
class Foo {
#secret = "Keyboard Cat";
method() {
console.log(this.#secret);
}
}
Foo.prototype.method();