【发布时间】:2021-05-27 05:14:58
【问题描述】:
我正在尝试代理一组对象,以便我可以将它们传递给第三方代码并暂时取消突变方法和设置器,然后撤销代理处理程序陷阱以恢复正常行为。我发现代理本质上对依赖this 的代码怀有敌意。
我很想知道 Javascript 代理如何以及为什么会破坏this 对其代理目标的绑定。在下面的示例中,我有一个简单的类,它在构造时获取一个值,将其存储为私有字段,并在属性访问时返回它。请注意:
- 在没有处理程序的情况下尝试通过代理访问属性会引发错误
- 通过
Reflect.get显式转发处理程序get陷阱可恢复正常行为
class Thing {
#value
constructor(value){
this.#value = value
}
get value(){
return this.#value
}
}
// Default behaviour
const thing1 = new Thing('foo')
attempt(() => thing1.value)
// No-op proxy breaks contextual access behaviour
const proxy1 = new Proxy(thing1, {})
attempt(() => proxy1.value)
// Reinstated by explicitly forwarding handler get call to Reflect
const proxy2 = new Proxy(thing1, {get: (target, key) =>
Reflect.get(target, key)
})
attempt(() => proxy2.value)
function attempt(fn){
try {
console.log(fn())
}
catch(e){
console.error(e)
}
}
这为 getter 访问提供了一种解决方法,但我不明白为什么会出现问题或为什么额外的代码可以修复它。当涉及到方法时,未处理的代理查询中的上下文冲突问题同样令人烦恼。在下面的代码中,value 属性变成了一个方法而不是一个 getter。在这种情况下:
- 默认行为仍然被破坏
-
Reflect.get不再有效 - 我可以在
get陷阱中显式绑定this - 但这并不是恢复预期行为
class Thing {
#value
constructor(value){
this.#value = value
}
value(){
return this.#value
}
}
// Default behaviour
const thing1 = new Thing('foo')
attempt(() => thing1.value())
// No-op proxy breaks contextual access behaviour
const proxy1 = new Proxy(thing1, {})
attempt(() => proxy1.value())
// Forwarding handler get trap to Reflect doesn't work
const proxy2 = new Proxy(thing1, {get: (target, key) =>
Reflect.get(target, key)
})
attempt(() => proxy2.value())
// Explicitly binding the returned method *does* work
const proxy3 = new Proxy(thing1, {get: (target, key) =>
target[key].bind(target)
})
attempt(() => proxy3.value())
// But this goes beyond reinstating normal behaviour
var {value} = thing1
attempt(() => value())
var {value} = proxy3
attempt(() => value())
function attempt(fn){
try {
console.log(fn())
}
catch(e){
console.error(e)
}
}
【问题讨论】:
-
您想要解决这个问题:“尝试代理一组对象”还是只是好奇为什么一个对象不能访问另一个对象的私有属性? Proxy 对象,即使是空实现仍然是一个对象。无论如何,我有一个解决方案可以让你实现你的目标(但与你想象的不同)。
-
哈哈我很感兴趣!那就继续吧……
标签: javascript javascript-proxy