javascript - 代理事件目标上的 addEventListener

标签 javascript proxy javascript-objects dom-events addeventlistener

我正在尝试创建一个基本上都是 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 收听),也可以是值的存储(代理对象在修改时负责调度事件)。到目前为止,此方法仅在您随身携带 时才有效。两个 targetstate ...

知道为什么我不能调用 addEventListener通过Proxy ?

从技术上讲,请调用 state.addEventListener()通过get原型(prototype)方法,所以我尝试定义get: Reflect.get在代理处理程序中,但它没有添加任何内容......(即使它确实达到了,因为我也尝试在那里添加 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/

相关文章:

javascript - CSS、JS 或 JQuery 中是否有一种方法可以根据位置更改文本的颜色?

proxy - 为什么 CNTLM 要求输入密码?

javascript - 从流式音频 Node js 中删除高频声音

javascript - Angular Material Design 具有强制选择功能的自动完成文本框

javascript - 在 Sencha Touch 2 中动态定义和加载具有不同代理存储的 View

javascript - 代理未检测到嵌套数组的更改

javascript - 如何在具有对象的React App中循环遍历javascript数组并获得具有特定值的属性的计数

javascript - V8如何处理“大对象空间”中的对象

javascript - 将Javascript对象格式化为新数组

javascript - CSS类不适用于节点