Reputation: 24739
I've noticed a strange Javascript error which only seems to happen on Internet Explorer 8. Basically, on IE-8 if you have an event handler function which captures the event object in a closure, the event "type" property seems to become invalidated from within the closure.
Here's a simple code snippet which reproduces the error:
<html>
<head>
<script type="text/javascript">
function handleClickEvent(ev)
{
ev = (ev || window.event);
alert(ev.type);
window.setTimeout(function() {
alert(ev.type); // Causes error on IE-8
}, 20);
}
function foo()
{
var query = document.getElementById("query");
query.onclick = handleClickEvent;
}
</script>
</head>
<body>
<input id="query" type="submit" />
<script type="text/javascript">
foo();
</script>
</body>
</html>
So basically, what happens here is that within the handleClickEvent
function, we have the event object ev
. We call alert(ev.type)
and we see the event type is "click". So far, so good. But then when we capture the event object in a closure, and then call alert(ev.type)
again from within the closure, now all of a sudden Internet Explorer 8 errors, saying "Member not found" because of the expression ev.type
. It seems as though the type
property of the event object is mysteriously gone after we capture the event object in a closure.
I tested this code snippet on Firefox, Safari and Chrome, and none of them report an error condition. But in IE-8, the event object seems to become somehow invalidated after it's captured in the closure.
Question: Why is this happening in IE-8, and is there any workaround?
Upvotes: 4
Views: 1765
Reputation: 708186
Yes, this happens because the event data structure is a global variable in IE8 so it gets overwritten by other events when they happen. If you need it to remain around for the closure, you will have to make an actual copy of the event data structure in the closure so you can reference the static copy rather than the one global structure that gets reused by IE8.
Making a copy of the data structure consists of making a new object and copying over all the properties. If any properties themselves are objects or arrays, you have to make copies of them too (just assigning them to the new object will assign references, not copies).
Or, if you only need the type
, then just assign the type
to a local variable in the closure and just reference that like this.
function handleClickEvent(ev)
{
ev = (ev || window.event);
// save copy of type locally so we can use it later in setTimeout()
var type = ev.type;
alert(type);
window.setTimeout(function() {
alert(type);
}, 20);
}
Upvotes: 5