[英]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
中, target
是aSecret
, propName
是"secret"
, receiver
是proxy
。 Reflect.get
將使用receiver
(代理)作為this
調用 getter 函數,因為這就是第三個參數的用途,即操作期間this
的值。 在操作期間this
是proxy
而不是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 方法中的this
是target
( aSecret
),而不是receiver
( proxy
),因此訪問私有字段是有效的。
代理真的可以提供對類的私有字段的訪問嗎?
代理不能公開尚未提供非私有訪問方式的實例的私有字段,不。 但它可以提供對可以訪問這些字段的 getter 和方法的訪問。 但是你必須提供正確的this
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.