簡體   English   中英

代理真的可以提供對類的私有字段的訪問嗎?

[英]Can a Proxy really provide access to private fields of a class?

我正在閱讀此處的文檔,這似乎暗示即使對於私有字段,也可以通過代理訪問它們。 請參閱以“....修復此問題....”開頭的簡介。 但是給出的示例不起作用。 我的代碼如下所示:

具有私有字段的類:

class Danger {
    #areYouSure = "magic";

    grave(){
        console.log("Yes, grave danger");
        return true;
    }

}

module.exports = Danger;

嘗試使用代理訪問它:

const Danger = require('./testing-private');

const handler = {
    get(target, property, receiver){
        return target[property];
    }
};
const dangerProxy = new Proxy(new Danger(), handler);

console.log("--------------------------------------", dangerProxy.areYouSure);

這打印出來:

-------------------------------------- undefined

如果我用“dangerProxy.#areYouSure”替換“dangerProxy.areYouSure”。 我明白了

/home/zaphod/code/math/js-experiments/src/danger-proxy.js:29
console.log("--------------------------------------", dangerProxy.#areYouSure);
                                                                 ^

SyntaxError: Private field '#areYouSure' must be declared in an enclosing class
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1032:15)
    at Module._compile (node:internal/modules/cjs/loader:1067:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1155:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
    at node:internal/main/run_main_module:17:47

有沒有辦法讓這個工作或者我的期望不正確?

文檔的部分實際上是關於 getter 屬性中的this (盡管對此不是很清楚),而不是關於私有屬性本身。 只是當 getter 訪問私有字段時,getter 中this的值更重要。

假設我們使用偽私有屬性(僅按約定私有)做同樣的事情:

 class Secret { _secret; constructor(secret) { this._secret = secret; } get secret() { return this._secret.replace(/\d+/, "[REDACTED]"); } } const aSecret = new Secret("123456"); console.log(aSecret.secret); // [REDACTED] // Looks like a no-op forwarding... const proxy = new Proxy(aSecret, {}); console.log(proxy.secret); // [REDACTED]

如您所見,這是有效的。 但是,當真正的私有字段沒有時,為什么它會起作用? 因為在 getter 調用期間this的值。 讓我們看看this是什么:

 class Secret { _secret; constructor(secret) { this._secret = secret; } get secret() { console.log(`this === aSecret? ${this === aSecret}`); console.log(`this === proxy? ${this === proxy}`); return this._secret.replace(/\d+/, "[REDACTED]"); } } const aSecret = new Secret("123456"); const proxy = new Proxy(aSecret, {}); // (Had to move this, but it doesn't change anything important) console.log(aSecret.secret); // [REDACTED] console.log(proxy.secret); // [REDACTED]

當我們直接使用aSecret時, this (可能很明顯)是aSecret

this === aSecret? true
this === proxy? false
[REDACTED]

...但是當我們通過代理時, this是代理:

this === aSecret? false
this === proxy? true
[REDACTED]

這是因為get陷阱的默認實現實際上如下所示:

get(target, propName, receiver) {
    return Reflect.get(target, propName, receiver);
}

proxy.secret中, targetaSecretpropName"secret"receiverproxy Reflect.get將使用receiver (代理)作為this調用 getter 函數,因為這就是第三個參數的用途,即操作期間this的值。 在操作期間thisproxy而不是aSecret對於我們的偽私有示例來說並不重要,因為當 getter 方法嘗試訪問this._secret時,它會在代理上訪問它,然后從目標獲取它。 但這不適用於真正的私有字段,因為代理對象沒有私有字段。

他們提供的解決方案是將get陷阱從上面的默認設置更改為:

get(target, propName, receiver) {
    return target[propName];
    // The above is like `return Reflect.get(target, propName, target);`
    // Note `target` instead of `receiver` for third argument −^
}

這樣,getter 方法中的thistargetaSecret ),而不是receiverproxy ),因此訪問私有字段是有效的。

代理真的可以提供對類的私有字段的訪問嗎?

代理不能公開尚未提供非私有訪問方式的實例的私有字段,不。 但它可以提供對可以訪問這些字段的 getter 和方法的訪問。 但是你必須提供正確的this

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM