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

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

使用此代码:

function baz() {
  var x = "foo";

  function bar() {
    debugger;
  };
  bar();}baz();

我得到了一个意想不到的结果:

enter image description here

当我更改代码时:

function baz() {
  var x = "foo";

  function bar() {
    x;
    debugger;
  };
  bar();}

我得到了预期的结果:

enter image description here

另外,如果有人打电话到eval在内部函数中,我可以像我想做的那样访问我的变量(不管我传递给什么)eval).

同时,Firefoxdev工具在这两种情况下都提供了预期的行为。

Chrome的什么地方,调试器的行为不如Firefox那么方便?我观察这种行为已经有一段时间了,包括41.0.2272.43测试版(64位)。

是Chrome的javascript引擎在可能的情况下“平复”了这些功能吗?

有趣的是,如果我添加第二个变量,在内部函数中引用,x变量仍未定义。

我理解在使用交互式调试器时经常会出现范围和变量定义的怪癖,但在我看来,基于语言规范,应该有一个解决这些怪癖的“最佳”解决方案。所以我很好奇这是否是因为Chrome比Firefox更加优化。此外,这些优化在开发过程中是否可以很容易地被禁用(也许在开发工具打开时应该禁用这些优化?)。

此外,我还可以使用断点以及debugger声明。


慕虎7371278
浏览 508回答 3
3回答

慕雪6442864

我找到了一个V8发行报告这正是你想要的。现在,总结一下那份报告中所说的话.V8可以存储堆栈中函数的本地变量。或在堆上的“上下文”对象中。它将在堆栈上分配局部变量,只要函数不包含引用它们的任何内部函数。这是一个优化..如果任何内部函数是指局部变量,这个变量将放在上下文对象中(即堆上而不是堆栈上)。案例eval是特殊的:如果它是由一个内部函数调用的,全局部变量放在上下文对象中。上下文对象的原因是,通常您可以从外部函数返回内部函数,然后外部函数运行时存在的堆栈将不再可用。因此,内部函数访问的任何东西都必须生存于外部函数中,并且生活在堆上而不是堆栈上。调试器无法检查堆栈上的那些变量。关于调试中遇到的问题,有一个项目成员说:我能想到的唯一解决方案是,每当DevTools打开时,我们就会取消所有代码,并使用强制上下文分配重新编译。不过,在启用DevTools的情况下,这将显着地降低性能。下面是“如果任何内部函数引用变量,将其放入上下文对象”的示例。如果你运行这个,你就可以访问x在debugger声明,尽管x仅在foo职能,从未被称为!function baz() {   var x = "x value";   var z = "z value";   function foo () {     console.log(x);   }   function bar() {     debugger;   };   bar();}baz();

神不在的星期二

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

相关分类

JavaScript