ES6代理类,访问私有属性(无法从类未声明的对象中读取私有成员#hidden)

Mar*_*arc 9 javascript properties private ecmascript-6 es6-proxy

我正在研究代理对象、类和私有属性。并遇到了这个错误消息:

/home/marc/projects/playground/pipeline/clsss.js:14
        this.#hidden = !this.#hidden;
                             ^

TypeError: Cannot read private member #hidden from an object whose class did not declare it
    at Proxy.toggle (/home/marc/projects/playground/pipeline/clsss.js:14:30)
    at Object.<anonymous> (/home/marc/projects/playground/pipeline/clsss.js:37:19)
    at Module._compile (internal/modules/cjs/loader.js:1118:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1138:10)
    at Module.load (internal/modules/cjs/loader.js:982:32)
    at Function.Module._load (internal/modules/cjs/loader.js:875:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47
Run Code Online (Sandbox Code Playgroud)

重现代码:

/home/marc/projects/playground/pipeline/clsss.js:14
        this.#hidden = !this.#hidden;
                             ^

TypeError: Cannot read private member #hidden from an object whose class did not declare it
    at Proxy.toggle (/home/marc/projects/playground/pipeline/clsss.js:14:30)
    at Object.<anonymous> (/home/marc/projects/playground/pipeline/clsss.js:37:19)
    at Module._compile (internal/modules/cjs/loader.js:1118:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1138:10)
    at Module.load (internal/modules/cjs/loader.js:982:32)
    at Function.Module._load (internal/modules/cjs/loader.js:875:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47
Run Code Online (Sandbox Code Playgroud)

有没有办法处理代理类实例上的私有属性?

为什么这不适用于代理?

感谢您的任何提示/答案。

编辑:在 github 上发现了一个相关问题:https://github.com/tc39/proposal-class-fields/issues/106 我发现的一个快速技巧是使用:

class Parent {

    #hidden;

    constructor() {
        this.#hidden = false;
    }

    get hidden() {
        return this.#hidden;
    }

    toggle() {
        this.#hidden = !this.#hidden;
        console.log("Changed", this.#hidden)
        return this.#hidden;
    }

}


const p = new Parent();
const proxy = new Proxy(p, {
    get: (target, prop, receiver) => {
        return target[prop];
    }
});

console.log(p.toggle())
console.log(proxy.toggle())  // this is the problem
console.log(p.toggle())
Run Code Online (Sandbox Code Playgroud)

但这似乎非常不干净/错误。

Fra*_*ion 5

如果这是所需的行为,您可以将该方法绑定到构造函数上:

constructor() {
      this.#hidden = false;
      this.toggle = this.toggle.bind(this);
}
Run Code Online (Sandbox Code Playgroud)

演示:

constructor() {
      this.#hidden = false;
      this.toggle = this.toggle.bind(this);
}
Run Code Online (Sandbox Code Playgroud)

否则你可以代理类本身:

class Parent {

    #hidden;

    constructor() {
        this.#hidden = false;
        this.toggle = this.toggle.bind(this);
    }

    get hidden() {
        return this.#hidden;
    }

    toggle() {
        this.#hidden = !this.#hidden;
        console.log("Changed", this.#hidden)
        return this.#hidden;
    }

}


const p = new Parent();
const proxy = new Proxy(p, {
    get: (target, prop, receiver) => {
        return target[prop];
    }
});

console.log(p.toggle())
console.log(proxy.toggle())  // this is the problem
console.log(p.toggle())
Run Code Online (Sandbox Code Playgroud)


Ayz*_*ian 1

这是不可能的,请阅读它所说的错误消息,Cannot read private member #hidden from an object whose class did not declare it一旦您创建了代理并尝试从中访问某些内容,将不会与您正在包装的原始内容具有相同的类。

更新:您可以在此处阅读有关私有字段及其工作方式的更多信息https://developer.cdn.mozilla.net/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields