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

标签 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. Debugger 中,设置断点:setTimeout(f, 1000);

  4. 断点命中后,在控制台中计算x。结果:未定义

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

  5. 重新加载页面。第一次运行 f 时命中断点。

  6. 评估x。结果:5

  7. 继续执行,当再次命中断点时,计算x。同样的结果:5

我的假设:如果 Firefox 在第一次运行 f 时意识到不需要 x,那么它不会存储该值x“与”f。因此在随后调用 f 时,x 的值是 undefined。有趣的是,我在 Chrome 35 和 IE11 中看到了相同的行为。

问题: 这是怎么回事?我可以配置 Firefox 使 x 在第 4 步中计算出正确的值吗(见上文)?

最佳答案

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

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

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

因为它无法撤消已经完成的操作,所以当您第一次命中断点时它是未定义的。

即使禁用 JIT 编译器,也无法真正阻止这种情况的发生。虽然从技术上讲,您可以将垃圾收集限制设置得非常高以尝试阻止它这样做,或者甚至删除垃圾收集代码并重建 Firefox,但这非常愚蠢——您最终会泄漏大量内存,那将是比简单地刷新页面要麻烦得多。

有趣的是,如果您尝试做同样的事情,Firefox 31 (Aurora) 会提供更具描述性的错误消息:

Error: variable has been optimized out

关于javascript - 为什么 Firefox 会忘记变量的值?调试解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24069611/

相关文章:

swift 4 : Cannot assign value of type '(_) -> Void' to type '(() -> ())?'

javascript - 在 FireFox 中使用 javascript 解析日期

css - Firefox 背景图像错误

javascript - 在使用 SELECT 附近的 sql sintaxis 中出错,代码 : 'ER_PARSE_ERROR' , errno: 1064

如果设置了 session 变量,Javascript React 重定向

javascript - 在 V8 中使用数组(性能问题)

javascript - JS在函数表达式中不使用 "return"将函数转为对象

swift - 通知中心或关闭?

javascript - Angular Directive(指令)更新多个元素的高度以匹配最高的元素

javascript - 交叉引用工作表上的 For 循环和 if 语句