6

手順:

  1. Firefox 29.0.1 (Windows 7 x64) でページを開く:

    <!doctype html>
    <title>Test</title>
    <script>
        (function () {
            var x = 5, f = function () {
                setTimeout(f, 1000);
            };
            f();
        }());
    </script>
    
  2. 開発者ツール ( F12) を開きます。

  3. Debuggerで、以下にブレークポイントを設定します。setTimeout(f, 1000);

  4. ブレークポイントに到達したら、xコンソールで評価します。結果:undefined

    <code>x</code> が評価されるときのスクリーンショット

  5. ページをリロードします。の最初の実行でブレークポイントにヒットしますf

  6. 評価しxます。結果:5

  7. 実行を再開し、再びブレークポイントに到達したときに を評価しxます。同じ結果:5

私の仮定: Firefox が最初の実行時にfそれが必要ないことを認識した場合、それは"with"xの値を保存しません。したがって、後続の呼び出しでは、 isの値が呼び出されます。興味深いことに、Chrome 35 と IE11 で同じ動作が見られます。xffxundefined

質問: 何が起こっているのですか? xステップ 4 (上記参照) で正しい値を評価するように Firefox を設定できますか?

4

1 に答える 1

6

あなたの推測は正しいようです。問題は、デバッガーが実行されていないときに変数が最適化または削除されたことです。デバッガーを実行してページを更新すると、関数の内部スコープにアクセスできるようになるため、コードをより簡単にデバッグできます。

そこにブレークポイントがなければ、これは不可能なので、JIT コンパイラーを無効にする必要があります。ガベージ コレクターは、これらがスコープ内で参照できることにも注意するため、これらの変数は削除されません。

JIT コンパイラが実行されている場合、x変数がどこにも使用されていないことを認識し、生成されたコードからそれを削除します。JIT コンパイラが実行されていない場合、変数を参照するものがないため、GC サイクルの実行時にガベージ コレクション (GC) によって変数が削除されます。

既に行ったことを元に戻すことはできないため、最初にブレークポイントに到達したときは未定義です。

JIT コンパイラを無効にしても、これを完全に防ぐことはできません。技術的には、ガベージ コレクションの制限を非常に高く設定して停止させたり、ガベージ コレクション コードを削除して Firefox を再構築したりすることもできますが、それはかなりばかげています。単純にページを更新するよりもはるかに手間がかかります。

興味深いことに、Firefox 31 (Aurora) で同じことをしようとすると、よりわかりやすいエラー メッセージが表示されます。

Error: variable has been optimized out
于 2014-06-06T09:51:32.620 に答える