7

如果我在 Chrome 开发人员工具中运行此代码:

var test = (function () {

  var publicFunction,
      privateFunction1,
      privateFunction2;

  privateFunction1 = function privateFunction1() {
    return true;
  };

  privateFunction2 = function privateFunction2() {
    return true;
  };

  publicFunction = function publicFunction() {
    privateFunction1();
    debugger;
  };

  return {
    publicFunction: publicFunction
  };
})();

为什么privateFunction1在断点范围内,而不在范围内privateFunction2

Chrome 开发工具截图

4

1 回答 1

4

有趣的问题。

privateFunction2 范围内publicFunction,但publicFunction从未实际使用它。我相信您在调试器中看到的是因为 V8(Chrome 的 JavaScript 引擎)出于各种原因(包括最小化内存使用)优化了闭包的内容。

理论上,根据规范,publicFunction关闭(具有持久引用)定义范围内的所有符号。具体来说,为调用最外层的匿名函数创建了一个执行上下文,并且该执行上下文具有一个词法环境,该环境具有一个关联的绑定对象,该对象publicFunction具有隐式的匿名引用。该绑定对象在其上具有(理论上)名称publicFunctionprivateFunction1privateFunction2和其他一些东西(arguments等等)的属性。

但问题是,publicFunction它实际上并没有引用任何东西privateFunction1,而且它的代码已经到位,它不能引用其他任何东西。要让它引用其他任何东西,您必须更改它的代码,当然 V8 会做出不同的决定。中的代码publicFunction没有eval(string)ornew Function(string)调用,因此 V8 可以自由地对其引用的符号进行静态分析。这意味着,在没有调试器的情况下,绑定对象保留这些其他属性毫无意义。它们从未被使用过。

由于 V8 是一个积极优化的编译器(是的,编译器),显然它从执行上下文的绑定对象中删除了死属性。

如果我添加一些用于任何publicFunction用途privateFunction2的东西,然后我可以像我一样从控制台引用它privateFunction1

于 2013-02-13T13:12:28.420 回答