步骤:
在Firefox 29.0.1(Windows 7 x64)中打开页面:
<!doctype html>
<title>Test</title>
<script>
(function () {
var x = 5, f = function () {
setTimeout(f, 1000);
};
f();
}());
</script>
打开开发人员工具( F12 )。
在调试器中,设置断点:setTimeout(f, 1000);
点击断点后,在控制台中评估x
。结果:undefined
重新加载页面。第一次运行f
时会触发断点。
评估x
。结果:5
恢复执行,再次点击断点时,评估x
。结果相同:5
我的假设:如果Firefox在f
的第一次运行中意识到不需要x
,那么它就不会存储{{1}的值&#34;与&#34; x
。因此,在后续调用f
时,f
的值为x
。有趣的是,我在Chrome 35和IE11中看到了相同的行为。
问题: 发生了什么事?我是否可以配置Firefox以使undefined
在步骤4中评估其正确值(见上文)?
答案 0 :(得分:5)
看来你的假设是正确的。问题是当调试器未运行时,变量已被优化或删除。当您运行调试器刷新页面时,它会让您访问函数的内部范围,以便您可以更轻松地调试代码。
如果那里没有断点,那么这是不可能的,因此必须禁用JIT编译器才能这样做。垃圾收集器还指出,这些仍然可以在范围内引用,因此不会删除这些变量。
如果JIT编译器正在运行,它将识别x
变量未在任何地方使用,并从生成的代码中删除它。如果JIT编译器不正在运行,则垃圾收集(GC)将在GC循环运行时删除该变量,因为没有引用该变量。
因为它无法撤消它已经完成的内容,所以当你第一次点击断点时它是未定义的。
即使禁用JIT编译器,也无法真正防止这种情况发生。虽然从技术上讲你可以设置垃圾收集限制真的很高,试图阻止它这样做,甚至删除垃圾收集代码并重建Firefox,这是非常愚蠢的 - 你最终会泄漏一堆内存,这将是比简单刷新页面更麻烦。
有趣的是,如果您尝试执行相同的操作,Firefox 31(Aurora)会提供更具描述性的错误消息:
Error: variable has been optimized out