Клонирование объекта события 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);
}