cloning javascript event object

前端 未结 4 1457
情歌与酒
情歌与酒 2020-11-28 13:07

Anybody know how to do a deep copy/cloning of a native javascript event object? I know I can create a new event object and set the appropriate properties manually to match

相关标签:
4条回答
  • 2020-11-28 13:17

    Option 1: Making a new event with modification

    You could make an Object.assign-alike using proxies and construct a new event without modifying the original event

    Example:

    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
    }

    This way you will use the same options as the original event that includes bubble, cancelable, key modifier, etc (doe it don't include any target as you are meant to dispatch the modified event on something else)

    Option 2: Define new properties

    Keeping the original event but override a key using Object.defineProperty you could use defineProperties if you want to add more than just one.

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

    0 讨论(0)
  • 2020-11-28 13:19

    Above code will not copy any getters/setters properly. Try:

    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;
    }
    
    0 讨论(0)
  • 2020-11-28 13:26

    For your purposes I'd just make it a prototype of a new object constructor and override the ones you want changed. Cloning in JS gets messy due to the circular reference issue so it may not be the quick and dirty solution you were hoping for.

    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
    ...*/
    

    In this case the 'cloned' object is the prototype object of the new object. 'this.' properties are checked for before the prototype object so these will override. Or you could just attach properties after the object is built.

    0 讨论(0)
  • 2020-11-28 13:36

    Inspired by Kofifus answer I just do that

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

    or just

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

    it returns a new object that protects you from edit the original object. but let you read and edit the property. thanks to js prototype chain

    0 讨论(0)
提交回复
热议问题