更改本机浏览器事件的最佳方法是什么?

jan*_*mon 5 javascript

我试图currentTarget用vanilla javascript 临时修改事件的属性.

我的主要目标是在事件快速启动时实现非常快速的实现,而不是更改原始事件,或者至少在操作完成后将原始事件恢复为原始状态.

不幸的是,原型继承失败了Illegal invocation(chrome)或'get currentTarget' called on an object that does not implement interface Event.(firefox)或The Event.currentTarget getter can only be used on instances of Event(safari)错误:

// Trigger event for demonstration 
// in a real scenario that would be caused by a user
var event = new Event('demo');
document.documentElement.addEventListener('demo', eventHandler1, false);
document.documentElement.addEventListener('demo', eventHandler2, false);
document.documentElement.addEventListener('demo', eventHandler3, false);
document.documentElement.dispatchEvent(event);

// The event handlers:
function eventHandler1(event) {
  event.currentTarget = 'MyCustomValue';
  console.log(1, event.type, event.currentTarget); // <- won't output MyCustomValue
}

function eventHandler2(event) {
  try {
    var clone = Object.create(event);
    clone.currentTarget = 'MyCustomValue';
    console.log(2, event.type, clone.currentTarget);
  } catch (e) {
    console.log(2, e.message); // <- will log an Illegal invocation error
  }
}

function eventHandler3(event) {
  var Clone = function() {
    this.currentTarget = 'MyCustomValue';
  };
  Clone.prototype = event;
  try {
    var clone = new Clone();
    console.log(3, event.type, clone.currentTarget);
  } catch (e) {
    console.log(3, e.message); // <- will log an Illegal invocation error
  }
}
Run Code Online (Sandbox Code Playgroud)

对于现代浏览器,我们可以使用一个Proxy对象但是我很乐意找到支持IE11的解决方案.

你有任何提示如何使用vanilla javascript实现这一点吗?

ibr*_*rir 2

概念:

第一个示例不起作用,因为您尝试使用currentTarget赋值来覆盖该值,该值实际上不会被覆盖,因为 没有 setter currentTarget,只有一个 getter 。

至于第二个和第三个示例,会抛出错误,因为您调用了currentTarget错误的对象(即,this是克隆而不是原始事件)。

event要解决此问题,只需使用附加到实例的新 getter 或属性(而不是赋值)来隐藏 getter 本身(位于原型中)Object.defineProperty

例子:

var event = new Event('demo');
document.documentElement.addEventListener('demo', eventHandler, false);
document.documentElement.dispatchEvent(event);

function eventHandler(event) {
  Object.defineProperty(event, "currentTarget", {
    value: "MyCustomValue"
  });

  console.log(event.type, event.currentTarget);
}
Run Code Online (Sandbox Code Playgroud)

恢复能力:

由于新属性被分配给实例本身而不是其原型(换句话说,新属性遮盖了原型中的 getter),因此我们可以稍后将其删除以恢复回来。但要做到这一点,我们必须使其可配置,否则我们将无法删除它:

Object.defineProperty(event, "currentTarget", {
  value: "MyCustomValue",
  configurable: true
});
Run Code Online (Sandbox Code Playgroud)

当我们想要恢复时,我们只需将其删除,如下所示:

delete event.currentTarget;
Run Code Online (Sandbox Code Playgroud)

例子:

Object.defineProperty(event, "currentTarget", {
  value: "MyCustomValue",
  configurable: true
});
Run Code Online (Sandbox Code Playgroud)

笔记:

您还可以创建currentTarget一个 getter 而不是属性,它也可以工作:

Object.defineProperty(event, "currentTarget", {
  get: function() { return "MyCustomValue"; },
  configurable: true
});
Run Code Online (Sandbox Code Playgroud)