4

我注意到一个奇怪的 Javascript 错误,它似乎只发生在 Internet Explorer 8 上。基本上,在 IE-8 上,如果你有一个在闭包中捕获事件对象的事件处理函数,则事件“类型”属性似乎变得无效从封闭内。

这是一个重现错误的简单代码片段:

<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>

所以基本上,这里发生的是在handleClickEvent函数中,我们有事件对象ev。我们打电话alert(ev.type),我们看到事件类型是“点击”。到现在为止还挺好。但是当我们在闭包中捕获事件对象,然后alert(ev.type)从闭包内再次调用时,现在突然 Internet Explorer 8 出现错误,说“找不到成员”,因为表达式ev.type。在我们在闭包中捕获事件对象之后,似乎type事件对象的属性神秘地消失了。

我在 Firefox、Safari 和 Chrome 上测试了这个代码片段,它们都没有报告错误情况。但是在 IE-8 中,事件对象在闭包中被捕获后似乎变得无效。

问题:为什么在 IE-8 中会发生这种情况,是否有任何解决方法?

4

1 回答 1

5

是的,这是因为事件数据结构是 IE8 中的全局变量,所以当它们发生时它会被其他事件覆盖。如果您需要它在闭包中保留,您将必须在闭包中制作事件数据结构的实际副本,以便您可以引用静态副本而不是被 IE8 重用的一个全局结构。

制作数据结构的副本包括制作一个新对象并复制所有属性。如果任何属性本身是对象或数组,您也必须制作它们的副本(只需将它们分配给新对象将分配引用,而不是副本)。

或者,如果您只需要type,那么只需将 分配给type闭包中的局部变量,然后像这样引用它。

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);
}
于 2012-10-24T16:57:46.203 回答