4

Internet Explorer 8 でのみ発生するように見える奇妙な Javascript エラーに気付きました。基本的に、IE-8 では、イベント オブジェクトをクロージャーでキャプチャするイベント ハンドラー関数がある場合、イベントの "type" プロパティが無効になるようです。クロージャーの中から。

エラーを再現する簡単なコード スニペットを次に示します。

<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関数内に event object があるということevです。を呼び出すalert(ev.type)と、イベント タイプが「クリック」であることがわかります。ここまでは順調ですね。しかし、クロージャでイベント オブジェクトをキャプチャし、クロージャ内から再度呼び出すとalert(ev.type)、突然 Internet Explorer 8 でエラーが発生し、式が原因で「メンバーが見つかりません」と表示されますev.typetypeクロージャでイベント オブジェクトをキャプチャした後、イベント オブジェクトのプロパティが不思議なことになくなっているように見えます。

このコード スニペットを Firefox、Safari、および Chrome でテストしましたが、いずれもエラー状態を報告しませんでした。しかし、IE-8 では、イベント オブジェクトがクロージャでキャプチャされた後、何らかの形で無効になっているようです。

質問: IE-8 でこの問題が発生するのはなぜですか? また、回避策はありますか?

4

1 に答える 1

5

はい、これは、イベント データ構造が IE8 のグローバル変数であるため、他のイベントが発生すると上書きされるためです。クロージャーのためにそれを残しておく必要がある場合は、IE8 によって再利用される 1 つのグローバル構造ではなく、静的コピーを参照できるように、クロージャー内のイベント データ構造の実際のコピーを作成する必要があります。

データ構造のコピーを作成するには、新しいオブジェクトを作成し、すべてのプロパティをコピーします。プロパティ自体がオブジェクトまたは配列である場合は、それらのコピーも作成する必要があります (それらを新しいオブジェクトに割り当てるだけで、コピーではなく参照が割り当てられます)。

または、 のみが必要な場合は、 をクロージャーのローカル変数に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 に答える