6

I have this custom stringify function which can handle circular references:

const customStringify = function (v) {
  return JSON.stringify(v, function(k, v) {
    if (v instanceof Node) {
      return 'Node';
    }
    if (v instanceof Window) {
      return 'Window';
    }
    return v;
  });
};

but if I use it to stringify an event object:

  window.addEventListener('click', function (ev) {   // MouseEvent
    const v = customStringify(ev);  // {"isTrusted":true}
  });

v is just string that looks like this:

{"isTrusted":true}

so bizarre. I tried a few other custom stringifying helper functions, and they all give me the same result.

I looked at this thread: How to stringify event object?

but my problem seems more specific.

  • I also looked to see if the MouseEvent has a `toJSON` method somewhere in the prototype chain, and I didn't see one –  Jan 02 '18 at 02:33
  • What are you hoping to accomplish by doing this? Or are you just curious? – Nick Tomlin Jan 02 '18 at 02:42
  • my goal is to pass event data between threads on the front-end (message passing) –  Jan 02 '18 at 04:48

1 Answers1

3

JSON.stringify ignores non-enumerable properties, and most of the properties of a MouseEvent are (apparently) non-enumerable:

document.querySelector('button').addEventListener('click', ev => {
  let props = ['isTrusted', 'target', 'clientX', 'clientY', 'layerX', 'layerY'];
  props.forEach(prop => {
    console.log(prop + '?', ev.propertyIsEnumerable(prop));
  });
});
<button>Try it!</button>

You can call each property out by name and make it enumerable before handing the event off to JSON.stringify:

document.querySelector('button').addEventListener('click', ev => {
  let props = ['target', 'clientX', 'clientY', 'layerX', 'layerY'];
  props.forEach(prop => {
    Object.defineProperty(ev, prop, {
      value: ev[prop],
      enumerable: true,
      configurable: true
    });
  });
  console.log(JSON.stringify(ev));
});
<button>Try it again!</button>
AuxTaco
  • 4,883
  • 1
  • 12
  • 27