为了账号安全,请及时绑定邮箱和手机立即绑定

为什么Chrome调试器认为封闭局部变量是未定义的?

为什么Chrome调试器认为封闭局部变量是未定义的?

慕虎7371278 2019-06-19 19:22:24
为什么Chrome调试器认为封闭局部变量是未定义的?使用此代码:function baz() {   var x = "foo";   function bar() {     debugger;   };   bar();}baz();我得到了一个意想不到的结果:当我更改代码时:function baz() {   var x = "foo";   function bar() {     x;     debugger;   };   bar();}我得到了预期的结果:另外,如果有人打电话到eval在内部函数中,我可以像我想做的那样访问我的变量(不管我传递给什么)eval).同时,Firefoxdev工具在这两种情况下都提供了预期的行为。Chrome的什么地方,调试器的行为不如Firefox那么方便?我观察这种行为已经有一段时间了,包括41.0.2272.43测试版(64位)。是Chrome的javascript引擎在可能的情况下“平复”了这些功能吗?有趣的是,如果我添加第二个变量,是在内部函数中引用,x变量仍未定义。我理解在使用交互式调试器时经常会出现范围和变量定义的怪癖,但在我看来,基于语言规范,应该有一个解决这些怪癖的“最佳”解决方案。所以我很好奇这是否是因为Chrome比Firefox更加优化。此外,这些优化在开发过程中是否可以很容易地被禁用(也许在开发工具打开时应该禁用这些优化?)。此外,我还可以使用断点以及debugger声明。
查看完整描述

3 回答

?
慕雪6442864

TA贡献1812条经验 获得超5个赞

我找到了一个V8发行报告这正是你想要的。

现在,总结一下那份报告中所说的话.V8可以存储堆栈中函数的本地变量。在堆上的“上下文”对象中。它将在堆栈上分配局部变量,只要函数不包含引用它们的任何内部函数。这是一个优化..如果任何内部函数是指局部变量,这个变量将放在上下文对象中(即堆上而不是堆栈上)。案例eval是特殊的:如果它是由一个内部函数调用的,局部变量放在上下文对象中。

上下文对象的原因是,通常您可以从外部函数返回内部函数,然后外部函数运行时存在的堆栈将不再可用。因此,内部函数访问的任何东西都必须生存于外部函数中,并且生活在堆上而不是堆栈上。

调试器无法检查堆栈上的那些变量。关于调试中遇到的问题,有一个项目成员:

我能想到的唯一解决方案是,每当DevTools打开时,我们就会取消所有代码,并使用强制上下文分配重新编译。不过,在启用DevTools的情况下,这将显着地降低性能。

下面是“如果任何内部函数引用变量,将其放入上下文对象”的示例。如果你运行这个,你就可以访问xdebugger声明,尽管x仅在foo职能,从未被称为!

function baz() {
  var x = "x value";
  var z = "z value";

  function foo () {
    console.log(x);
  }

  function bar() {
    debugger;
  };

  bar();}baz();


查看完整回答
反对 回复 2019-06-19
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

我在NodeJS中也注意到了这一点。我相信(我承认这只是猜测),当代码被编译时,如果x不出现在里面bar,它不会x的范围内可用。bar..这可能会使它稍微更有效率;问题是有人忘记了(或者根本不在乎),即使没有x在……里面bar,您可能决定运行调试器,因此仍然需要访问x从里面bar.


查看完整回答
反对 回复 2019-06-19
  • 3 回答
  • 0 关注
  • 507 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信