javascript - 为什么 Chrome 调试器在 Closure 中访问变量时未定义?

标签 javascript google-chrome google-developer-tools

<分区>

代码:

function test4() {
    var x = 10;
    var y = 100;
    // inner referred x only
    function inner () {
        console.log(x);
        debugger;
    }
    // inner2 referred y to make sure y is in the scope of inner
    function inner2 () {
        console.log(y);
    }
    return inner;
}
var foo = test4();
foo();

yinner 的范围内,甚至只有从未使用过的 inner2 引用它。我检查了范围内的结果,xy 在那里:

x and y in closure

但是当我在监视面板和控制台中检查变量时,我无法获取所有变量:

can't get y in watch panel

y 在范围内但在使用调试器时未定义,这很奇怪。 那么,这是否意味着调试器无法访问当前上下文中未使用的变量,即使它在闭包中,还是只是一个错误? (我的chrome版本是51.0.2704.103m)

类似于Why does Chrome debugger think closed local variable is undefined?但不一样。因为我的代码中的 inner2 确保 y 在闭包中。实际上我的问题与Louis's answer相反在那个问题下。

最佳答案

您是范围优化内部机制的第一手观察者。作用域优化正在检查当前作用域中使用了哪些变量,并优化了对未使用变量的访问。这是因为在 javascript 的 JIT 编译生成的机器代码中,变量命名的整个概念都丢失了。但是,为了保持 javascript 合规性,JIT 编译器将一组使用过的局部变量关联到每个 javascript 函数。观察以下代码。

(function(){
  "use strict";
  var myVariable = NaN; // |Ref1|
  var scopedOne = (function(){
    var myVariable = 101; // |Ref2|
    return x => x * myVariable;
  })();
  var scopedTwo = (function(){
    var myVariable = -7; // |Ref3|
    return x => x / myVariable;
  })();
  console.log("scopedOne(2):  ", scopedOne(2));
  console.log("scopedTwo(56): ", scopedTwo(56))
})();

如上所示,Javascript 是一种范围限定的基于堆栈的语言。如果 Javascript 不是作用域语言,那么函数中使用的变量将取决于函数执行位置的变量值。例如,如果没有作用域,scopedOne 将在 |Ref1| (NaN) 而不是 |Ref2 处使用 myVariable 的值| (101) 并将 NaN 记录到控制台。回到重点,在机器代码中,当调试器进来时,它只能弄清楚内存中的实际位置是使用变量的位置,因为只有那些内存位置才持久保存到机器代码中,因为只有那些变量被使用过.其余变量的存储位置对它来说仍然是个谜。正如您所观察到的,这具有使范围内未使用的变量对该函数“不可见”的次要副作用。但是,有一个解决方案。

要避免这个问题,只需将 debugger; 语句包装在一个 eval 中,以强制浏览器对范围内的所有变量进行昂贵的变量查找。基本上,浏览器必须返回原始源代码,检查范围内变量的原始名称,并找出 JIT 生成的机器代码存储变量值的位置。打开开发人员工具并运行下面的代码片段。然后到“Call Stack”面板中的prior level,观察变量y的值的可见性如何从eval内部可见变为外部不可见评估

function test4() {
    var x = 10;
    var y = 100;
    // inner referred x only
    function inner () {
        console.log(x);
        eval("debugger;");
    }
    // inner2 referred y to make sure y is in the scope of inner
    function inner2 () {
        console.log(y);
    }
    return inner;
}
var foo = test4();
foo();

关于javascript - 为什么 Chrome 调试器在 Closure 中访问变量时未定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39361117/

相关文章:

google-chrome - Vue - Chrome 开发者控制台中的混合内容警告

javascript - Bootstrap容器中的背景色在Electron中不起作用

javascript - 属性 'submitAction' 在类型 '{}' 中缺失,但在类型中需要

javascript - 如何将一个传单标记添加到多个图层组?

javascript - 谷歌浏览器 - 这是 BUG 吗? Javascript 问题?触摸屏输入不工作

javascript - 运行 V8 时如何知道已编译哪些 javascript

javascript - 在浏览器中获取源映射的源位置

javascript - 动画和过渡同时进行?

javascript - Chrome NaCl 与 V8 有什么关系吗?

javascript - 如何解释 vue.js 中 console.log() 的这种奇怪行为?