我试图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实现这一点吗?
第一个示例不起作用,因为您尝试使用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)
| 归档时间: |
|
| 查看次数: |
137 次 |
| 最近记录: |