javascript - 重新定义类的方法时无法访问私有(private)成员

标签 javascript typescript

当使用#定义一个私有(private)成员,然后重新定义某个使用这个私有(private)成员的成员时,你会发现不能再使用了:

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

为什么?在这种情况下,我所做的就是围绕原始方法。请注意,此示例是在 TypeScript 中使用装饰器的显着简化。我怎样才能解决这个问题,同时仍然能够重新定义和“更改”方法?


这是同样的事情,但使用了 TypeScript 装饰器:

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();

Playground

最佳答案

您犯的错误是将方法应用于目标,即Foo.prototype,而不是通过以下方式应用于new Foo实例this 关键字:

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 没有 #secret 私有(private)字段。你会得到同样的错误

class Foo {
    #secret = "Keyboard Cat";
    
    method() {
        console.log(this.#secret);
    }
}

Foo.prototype.method();

关于javascript - 重新定义类的方法时无法访问私有(private)成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74010006/

相关文章:

javascript - Angular 2为每个数组对象添加键和值

reactjs - React hook form v7 Function 组件不能被赋予引用。尝试访问此引用将失败。你的意思是使用 React.forwardRef()

javascript - 使用 Jest 测试 Redux 和 Axios 获取中间件

angular - Angular 中不同模块的数组的类型是什么?

javascript - 对返回对象中的键值使用进行类型检查

javascript - Attributes.add、ScriptManager.RegisterStartupScript、ScriptManager.RegisterClientScriptBlock 不起作用

javascript - Flexigrid 从本地 json 对象加载数据

javascript - 使用 web-worker 卡住对象

javascript - 使用 jquery 转换页面加载时的超链接

javascript - 使用 D3 在选定的单选按钮之间切换