为什么Firefox会忘记变量的价值?调试解决方案?

fek*_*lee 5 javascript firefox closures firefox-developer-tools

脚步:

  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>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 打开开发人员工具(F12).

  3. 调试器中,设置断点:setTimeout(f, 1000);

  4. 一旦断点被​​击中,请x在控制台中进行评估.结果:undefined

    屏幕截图显示何时评估<code>f</code>.</p></li>
<li><p>评估<code>x</code>.结果:<code>5</code></p></li>
<li><p>恢复执行,再次点击断点时,进行评估<code>x</code>.相同的结果:<code>5</code></p></li>
</ol>

<p><strong>我的假设:</strong>如果Firefox在第一次运行时<code>f</code>意识到<code>x</code>不需要,那么它不会存储<code>x</code>f.所以在后续调用f的值xundefined.有趣的是,我在Chrome 35和IE11中看到了相同的行为.

    问题:发生了 什么事?我是否可以将Firefox配置为x在步骤4中评估其正确值(参见上文)?

Qan*_*avy 5

看来你的假设是正确的.问题是当调试器未运行时,变量已被优化或删除.当您在调试器运行时刷新页面时,它会让您访问函数的内部范围,以便您可以更轻松地调试代码.

如果那里没有断点那么这是不可能的,因此必须禁用JIT编译器才能这样做.垃圾收集器还指出这些仍然可以在范围内引用,因此不会删除这些变量.

如果JIT编译器正在运行,它将识别该x变量未在任何地方使用,并从生成的代码中删除它.如果JIT编译器没有运行,垃圾收集(GC)将在GC循环运行时删除变量,因为没有引用该变量.

因为它无法撤消它已经完成的内容,所以当你第一次点击断点时它是未定义的.

即使禁用JIT编译器,也无法真正防止这种情况发生.虽然从技术上讲你可以设置垃圾收集限制真的很高,试图阻止它这样做,甚至删除垃圾收集代码并重建Firefox,这是非常愚蠢的 - 你最终会泄漏一堆内存,这将是比简单刷新页面更麻烦.

有趣的是,如果您尝试执行相同的操作,Firefox 31(Aurora)会提供更具描述性的错误消息:

Error: variable has been optimized out
Run Code Online (Sandbox Code Playgroud)