我正在尝试创建一个基本上既是 Proxy
又是 EventTarget
的对象。目标是能够订阅对此对象所做的任何更改。
我是这样定义这个对象的:
const target = new EventTarget()
const state = new Proxy(target, {
set: (obj, key, value) => {
Reflect.set(obj, key, value)
obj.dispatchEvent(new CustomEvent('change', {detail: {key, value}}))
},
deleteProperty: (obj, key) => {
Reflect.deleteProperty(obj, key)
obj.dispatchEvent(new CustomEvent('change', {detail: {key, value: undefined}}))
}
})
此时我希望能够调用 state.addEventListener('change', console.log)
但这给了我一个错误:
Uncaught TypeError: Illegal invocation
所以这是有效的:
target.addEventListener('change', console.log)
state.foo = 'bar'
// logs the event
但正如我所说,我想要一个单一的统一对象,它既可以是目标(可以用 addEventListener
监听)又可以是值的存储(代理对象负责修改时调度事件)。到目前为止,此方法仅在您随身携带两者 target
和state
时才有效...
知道为什么我不能通过 Proxy
调用 addEventListener
吗?
从技术上讲,调用 state.addEventListener()
会通过 get
原型(prototype)方法,所以我尝试在代理处理程序,但它没有添加任何内容......(即使它确实达到了,因为我也尝试在那里添加一个 console.log
)
那么为什么我不能通过代理调用 addEventListener
但它直接在 target
对象上工作正常?
最佳答案
由于您使用的是代理,因此您确实需要像您想象的那样使用 getter,但您很可能没有绑定(bind)该函数,因此它会被正确的 this
调用。当您在没有它的情况下返回函数时失去该连接,它会引用代理对象,该代理对象本身并没有实现 EventTarget/EventListener 方法。
let target = document.documentElement;
let targetProxy = new Proxy(target,{
get:(obj,key)=>{
let value = Reflect.get(obj,key);
if(typeof(value) == "function"){
return value.bind(obj);
}
return value;
}
});
targetProxy.addEventListener('click',()=>console.log('clicked'));
关于javascript - 代理事件目标上的 addEventListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59109571/