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

时间:2014-06-05 20:24:26

标签: 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>
    
  2. 打开开发人员工具( F12 )。

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

  4. 点击断点后,在控制台中评估x。结果:undefined

    Screenshot showing when <code>x</code> is evaluated

  5. 重新加载页面。第一次运行f时会触发断点。

  6. 评估x。结果:5

  7. 恢复执行,再次点击断点时,评估x。结果相同:5

  8. 我的假设:如果Firefox在f的第一次运行中意识到不需要x,那么它就不会存储{{1}的值&#34;与&#34; x。因此,在后续调用f时,f的值为x。有趣的是,我在Chrome 35和IE11中看到了相同的行为。

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

1 个答案:

答案 0 :(得分:5)

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

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

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

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

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

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

Error: variable has been optimized out