Клонирование объекта события javascript

Кто-нибудь знает, как сделать глубокое копирование / клонирование нативного объекта события javascript? Я знаю, что могу создать новый объект события и установить соответствующие свойства вручную, чтобы соответствовать исходному событию, но было бы намного проще, если бы был способ просто клонировать.

3 ответа

Решение

Для ваших целей я бы просто сделал его прототипом нового конструктора объекта и переопределил те, которые вы хотите изменить. Клонирование в 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
...*/

В этом случае "клонированный" объект является объектом-прототипом нового объекта. 'этот.' свойства проверяются перед объектом-прототипом, поэтому они будут переопределены. Или вы можете просто прикрепить свойства после создания объекта.

Приведенный выше код не будет правильно копировать любые методы получения / установки. Пытаться:

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;
}

Вариант 1. Создание нового события с модификацией

Вы могли бы сделать Object.assign-похоже на использование прокси и создание нового события без изменения исходного события

Пример:

         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)
}

Вдохновленный Kofifus ответ, я просто делаю это

function cloneEvent(type, event) {
    var evt = new Event(type);
    return Object.setPrototypeOf(evt,event);
}
Другие вопросы по тегам