考虑:
let sel=document.getElementById('mys');
sel.onchange=function(e) {
console.log(e.currentTarget===null); // false
setTimeout(e => {
console.log(e.currentTarget===null); // true
}, 0, e);
}
<select id="mys">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
为什么e.currentTarget会在超时后发生变化?是一个浏览器(铬)错误?
如何将事件的确切克隆转移到超时功能?我尝试过简单的克隆,但currentTarget不可写,不能被删除..
答案 0 :(得分:1)
event.currentTarget和其他一些属性会发生变化。
在事件处理程序中执行上下文切换(setTimeout(... ,0);
)很常见,似乎正确传递事件(包括currentTarget等)的唯一方法是将其克隆如下。
请注意,这只是“足够好”......克隆不完全是原始事件,而且它的上下文不同......例如,clone.stopPropogation()没有意义......
如果您需要在克隆删除!d.writable || !d.configurable || !d.enumerable ||
let sel=document.getElementById('mys');
function cloneEvent(e) {
function ClonedEvent() {};
let clone=new ClonedEvent();
for (let p in e) {
let d=Object.getOwnPropertyDescriptor(e, p);
if (d && (!d.writable || !d.configurable || !d.enumerable || d.get || d.set)) {
Object.defineProperty(clone, p, d);
}
else {
clone[p] = e[p];
}
}
Object.setPrototypeOf(clone, e);
return clone;
}
sel.onchange=function(e) {
console.log(e.currentTarget);
let clone=cloneEvent(e);
setTimeout(e => {
console.log(e.currentTarget);
}, 0, clone);
}
<select id="mys">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
</select>
答案 1 :(得分:1)
受Joseph Marikle's comment的启发,我找到了真正的原因:
DOM Standard § 2.9. Dispatching events描述了该算法,我将在这里部分复制它:
[…]
5. If target is not relatedTarget or target is event’s relatedTarget, then:
[…]
9. While parent is non-null:
[…]
8. Otherwise, set target to parent and then:
[…]
9. If parent is non-null, then set parent to the result of invoking parent’s get the parent with event.
[…]
[…]
12. Set event’s eventPhase attribute to CAPTURING_PHASE.
[…]
14. For each tuple in event’s path, in reverse order:
1. […] invoke […]
15. For each tuple in event’s path, in order:
1. If tuple’s target is non-null, then set event’s eventPhase attribute to AT_TARGET.
2. Otherwise, set event’s eventPhase attribute to BUBBLING_PHASE.
3. […] invoke […]
[…]
6. Set event’s eventPhase attribute to NONE.
7. Set event’s currentTarget attribute to null.
[…]
因此,在事件处理完所有阶段(捕获,at_target,冒泡)之后,currentTarget
被分配了null
。
答案 2 :(得分:-1)
let sel=document.getElementById('mys');
sel.onchange=function({currentTarget}) {
console.log(currentTarget===null); // false
setTimeout(() => {
console.log(currentTarget===null); // false
}, 0);
}
<select id="mys">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
答案 3 :(得分:-2)
我建议您尝试使用其他浏览器,因为代码与我合作,我看不到代码段的任何问题。