如果我在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不在范围内?

最佳答案

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

从理论上讲,根据规范,publicFunction在定义它的范围内关闭(具有持久引用)。具体来说,为调用最外面的匿名函数创建了一个execution context,并且该执行上下文具有一个lexical environment和一个关联的binding object,该publicFunction具有隐式的匿名引用。该绑定(bind)对象具有(在理论上)名称为publicFunctionprivateFunction1privateFunction2和其他一些属性(arguments等)的属性。

但是问题是publicFunction实际上除了privateFunction1之外什么都没有引用,并且有了相应的代码,它不能引用其他任何东西。为了引用其他内容,您必须更改其代码,当然V8会做出不同的决定。 publicFunction中的代码没有eval(string)new Function(string)调用,因此V8可以自由对其引用的符号进行静态分析。这意味着,在没有调试器的情况下,保持对象的其他属性毫无意义。他们从未使用过。

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

如果我在使用publicFunction进行任何操作的privateFunction2中添加了某些内容,则可以从控制台引用它,就像我可以使用privateFunction1一样。

09-25 15:42