17

有人知道如何对原生 javascript 事件对象进行深度复制/克隆吗?我知道我可以创建一个新的事件对象并手动设置适当的属性以匹配原始事件,但如果有一种方法来克隆它会容易得多。

4

4 回答 4

12

上面的代码不会正确复制任何 getter/setter。尝试:

function cloneEvent(e) {
    if (e===undefined || e===null) return undefined;
    function ClonedEvent() {};  
    let clone=new ClonedEvent();
    for (let p in e) {
        let d=Object.getOwnPropertyDescriptor(e, p);
        if (d && (d.get || d.set)) Object.defineProperty(clone, p, d); else clone[p] = e[p];
    }
    Object.setPrototypeOf(clone, e);
    return clone;
}
于 2016-09-23T21:28:20.167 回答
11

出于您的目的,我只是将其作为新对象构造函数的原型并覆盖您想要更改的那些。由于循环引用问题,JS 中的克隆变得混乱,因此它可能不是您希望的快速而肮脏的解决方案。

function cloneEventObj(eventObj, overrideObj){

   if(!overrideObj){ overrideObj = {}; }

   function EventCloneFactory(overProps){
       for(var x in overProps){
           this[x] = overProps[x];
       }
    }

    EventCloneFactory.prototype = eventObj;

    return new EventCloneFactory(overrideObj);

}

//So add your override properties via an object
$el.click(function(e){
    var newEventObj = cloneEventObj(
        e,
        { target:document.body }
    );
    doSomething(newEventObj);
});

//or just stick 'em on manually after spitting the object out
/*...
var newEventObj = cloneEventObj(e);
newEventObj.target = document.body
...*/

在这种情况下,“克隆”对象是新对象的原型对象。'这。' 在原型对象之前检查属性,因此这些将被覆盖。或者您可以在构建对象后附加属性。

于 2012-09-24T22:29:12.183 回答
3

选项 1:通过修改创建新事件

您可以使用代理Object.assign创建一个-alike并构建一个新事件而不修改原始事件

例子:

function EventModifier (evt, obj) {
  const proxy = new Proxy(evt, {
    get: (target, prop) => obj[prop] || target[prop]
  })
  return new evt.constructor(evt.type, proxy)
}

onclick = evt => {
  evt = new EventModifier(evt, { altKey: true })
  // Dispatch the new event on something else
  console.log('clicked with alt key:', evt.altKey) // always true
}

这样,您将使用与原始事件相同的选项,包括气泡、可取消、键修饰符等(它是否不包含任何目标,因为您打算将修改后的事件调度到其他东西上)

选项 2:定义新属性

保留原始事件但使用Object.defineProperty您可以使用 defineProperties 覆盖一个键,如果您想添加的不仅仅是一个。

onclick = evt => {
  Object.defineProperty(evt, 'target', { value: document.querySelector('script') })
  console.log('target:', evt.target)
}

于 2020-10-07T21:50:01.387 回答
-1

受 Kofifus 回答的启发,我就是这样做的

function cloneEvent(type, event) {
    var evt = new Event(type);
    return Object.setPrototypeOf(evt,event);
}

要不就

function cloneEvent(event){
  return Object.create(event)
} 

它返回一个新对象,可以保护您免于编辑原始对象。但让您阅读和编辑该属性。谢谢js prototype chain

于 2017-07-04T09:40:32.230 回答