Gab*_*ley 155 javascript google-chrome google-chrome-devtools
使用此代码:
function baz() {
var x = "foo";
function bar() {
debugger;
};
bar();
}
baz();
Run Code Online (Sandbox Code Playgroud)
我得到了这个意外的结果:
当我更改代码时:
function baz() {
var x = "foo";
function bar() {
x;
debugger;
};
bar();
}
Run Code Online (Sandbox Code Playgroud)
我得到了预期的结果:
此外,如果eval
在内部函数中有任何调用,我可以按照我想要的方式访问我的变量(无论我传递给什么都没关系eval
).
同时,Firefox开发工具在两种情况下都给出了预期的行为.
与Chrome有什么关系,调试器的行为不如Firefox?我已经观察了这种行为一段时间,包括版本41.0.2272.43 beta(64位).
是不是Chrome的javascript引擎可以"平坦化"这些功能呢?
有趣的是,如果我添加在内部函数中引用的第二个变量,则该x
变量仍未定义.
我知道在使用交互式调试器时经常有范围和变量定义的怪癖,但在我看来,基于语言规范,应该是这些怪癖的"最佳"解决方案.所以我很好奇这是因为Chrome比Firefox更优化.以及在开发期间是否可以轻松禁用这些优化(也许在开放工具打开时应该禁用它们?).
此外,我可以使用断点和debugger
语句重现这一点.
Lou*_*uis 143
我发现了一个v8 问题报告,这正是你所要求的.
现在,总结该问题报告中的内容... v8可以存储堆栈上的函数本地变量或存储在堆上的"上下文"对象.它将在堆栈上分配局部变量,只要该函数不包含任何引用它们的内部函数.这是一个优化.如果任何内部函数引用局部变量,则此变量将放在上下文对象中(即在堆上而不是在堆栈上).的情况eval
是特殊的:如果它是由内部函数调用可言,所有的局部变量放在上下文对象.
上下文对象的原因是,通常你可以从外部函数返回一个内部函数,然后在外部函数运行时存在的堆栈将不再可用.因此,内部函数访问的任何东西都必须在外部函数中存活并且存在于堆上而不是堆栈上.
调试器无法检查堆栈中的那些变量.关于调试中遇到的问题,一位项目成员说:
我能想到的唯一解决方案是,无论何时启用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();
Run Code Online (Sandbox Code Playgroud)
Own*_*gic 29
就像@Louis所说的那样是由v8优化造成的.您可以遍历调用堆栈到此变量可见的框架:
或者替换debugger
为
eval('debugger');
Run Code Online (Sandbox Code Playgroud)
eval
将取消当前的块
我在nodejs中也注意到了这一点.我相信(我承认这只是一个猜测),当编译代码时,如果x
没有出现在内部bar
,它就不会x
在范围内提供bar
.这可能会使它更有效率; 问题是有人忘了(或不关心),即使没有有x
在bar
,你可能决定运行调试,因此仍然需要访问x
来自内部bar
.
归档时间: |
|
查看次数: |
27254 次 |
最近记录: |